Merged master into task/3622/decouple_opennebula_dcl_flow
This commit is contained in:
		
				commit
				
					
						6b7ae88f74
					
				
			
		
					 19 changed files with 296 additions and 142 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -35,3 +35,4 @@ secret-key | ||||||
| 
 | 
 | ||||||
| .env | .env | ||||||
| *.mo | *.mo | ||||||
|  | *.log | ||||||
|  |  | ||||||
							
								
								
									
										23
									
								
								Changelog
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								Changelog
									
										
									
									
									
								
							|  | @ -1,3 +1,26 @@ | ||||||
|  | 1.0.24: 2017-08-15 | ||||||
|  |     * #3699: [datacenterlight] Added oneadmin ssh key by default to the created VM via DCL landing | ||||||
|  |     * #3687: [datacenterlight] Added the name of the customer as description field of the stripe metadata | ||||||
|  |              [all] Added CustomUser as a parameter in get_anonymous_user function to resolve issues with tests | ||||||
|  | 1.0.23: 2017-08-11 | ||||||
|  |     * #3629: [datacentlight] Fixed navbar changing language from DE to EN between menus bug | ||||||
|  |     * #3623: [hosting] Fixed “Confirm Order” text appearing in “Invoice” place | ||||||
|  |     * #3633: [datacenterlight, hosting] Translated “All Rights Reserved” for German pages | ||||||
|  |     * #3627: [datacenterlight, hosting] Added border for payment warning message when the user has already submitted card information | ||||||
|  |     * #3620: [hosting] Updated SSH Key page with new style: new key choice page, upload key page, added icons for downloading and deleting key on mobile | ||||||
|  |     *        [hosting] bug fix: added modal icon and translation back for delete SSH Key | ||||||
|  |     * #3660: [datacenterlight] Rearranged desktop and mobile view for “Why Data Centre Light?” IPv6/SSD section | ||||||
|  |     * #3646: Added file with VM Template hosting migration | ||||||
|  |     * #3617: [hosting] Fixed Password reset confirmation page style bug | ||||||
|  |     * #3408: [hosting] Changed background image of signup/login background into smaller size | ||||||
|  |     * #3621: [hosting] Fixed signup/login/password reset page navbar logo overlapping with form | ||||||
|  |     * #3354: [hosting] Restyled modal | ||||||
|  |     * #3638: [hosting] Added “download” btn on generated key list for generated keys from upload your key page | ||||||
|  |     * #3655: [hosting] Disabled deleting SSH keys from other users | ||||||
|  |     * #3619: [datacenterlight, hosting] Replaced 'Lato-Light' and 'Lato-Regular' with only ‘Lato’ with appropriate font-weights | ||||||
|  |     * #3677: [hosting] Added wrapping for show SSH key modal text | ||||||
|  |     * #3683: [hosting] Fixed footer floating bug on VM creating page | ||||||
|  |     * #3676: [datacenterlight, hosting] Added missing card holder's name field migration | ||||||
| 1.0.22: 2017-07-30 | 1.0.22: 2017-07-30 | ||||||
|     * #3593: [datacenterlight] Removed underbars between social icons in index |     * #3593: [datacenterlight] Removed underbars between social icons in index | ||||||
|     * #3509: [datacenterlight, hosting] Made navbar transparent and removed mobile navbar bug in login/signup/reset-password |     * #3509: [datacenterlight, hosting] Made navbar transparent and removed mobile navbar bug in login/signup/reset-password | ||||||
|  |  | ||||||
|  | @ -4,10 +4,10 @@ | ||||||
|  * For details, see http://www.apache.org/licenses/LICENSE-2.0. |  * For details, see http://www.apache.org/licenses/LICENSE-2.0. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| @font-face { | /*@font-face { | ||||||
|     font-family: 'Lato-Light'; |     font-family: 'Lato-Light'; | ||||||
|     src: url('../fonts/Lato/Lato-Light.ttf'); |     src: url('../fonts/Lato/Lato-Light.ttf'); | ||||||
| } | }*/ | ||||||
| 
 | 
 | ||||||
| body, | body, | ||||||
| html { | html { | ||||||
|  | @ -22,7 +22,12 @@ h3, | ||||||
| h4, | h4, | ||||||
| h5, | h5, | ||||||
| h6 { | h6 { | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-family: 'Lato', sans-serif; | ||||||
|  |     font-weight: 300; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | button, input, optgroup, select, textarea { | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -143,13 +148,15 @@ h6 { | ||||||
| 
 | 
 | ||||||
| .navbar-default .navbar-nav>li>a { | .navbar-default .navbar-nav>li>a { | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .navbar-transparent .navbar-nav>li>a { | .navbar-transparent .navbar-nav>li>a { | ||||||
|     color: #fff; |     color: #fff; | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .navbar-transparent .navbar-nav>li>a:hover { | .navbar-transparent .navbar-nav>li>a:hover { | ||||||
|  | @ -202,13 +209,15 @@ h6 { | ||||||
| 
 | 
 | ||||||
| .navbar-transparent .nav-language .select-language { | .navbar-transparent .nav-language .select-language { | ||||||
|     color: #fff; |     color: #fff; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .nav-language .select-language span { | .nav-language .select-language span { | ||||||
|     margin-left: 5px; |     margin-left: 5px; | ||||||
|     margin-right: 5px; |     margin-right: 5px; | ||||||
|     font-family: 'Lato', sans-serif; |     /*font-family: 'Lato', sans-serif;*/ | ||||||
|  |     font-weight: normal; | ||||||
| } | } | ||||||
| .nav-language .drop-language{ | .nav-language .drop-language{ | ||||||
|     /*position: absolute;*/ |     /*position: absolute;*/ | ||||||
|  | @ -237,7 +246,8 @@ h6 { | ||||||
| .nav-language .drop-language a{ | .nav-language .drop-language a{ | ||||||
|    cursor: pointer; |    cursor: pointer; | ||||||
|    padding: 5px 10px !important; |    padding: 5px 10px !important; | ||||||
|    font-family: 'Lato-Light', sans-serif; |    /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |    font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Show the dropdown menu on hover */ | /* Show the dropdown menu on hover */ | ||||||
|  | @ -260,7 +270,8 @@ h6 { | ||||||
| .navbar-transparent .nav-language .drop-language a { | .navbar-transparent .nav-language .drop-language a { | ||||||
|     color: #fff; |     color: #fff; | ||||||
|     padding: 5px 10px !important; |     padding: 5px 10px !important; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| /* .nav-language:hover .drop-language{ | /* .nav-language:hover .drop-language{ | ||||||
|     display: block; |     display: block; | ||||||
|  | @ -343,7 +354,7 @@ h6 { | ||||||
| 
 | 
 | ||||||
| .intro-message>h1 { | .intro-message>h1 { | ||||||
|     margin: 0; |     margin: 0; | ||||||
|     font-weight: 400; |     font-weight: 300; | ||||||
|     font-size: 6em; |     font-size: 6em; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -792,7 +803,8 @@ tech-sub-sec h2 { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .percent-text { | .percent-text { | ||||||
|     font-family: 'Lato', sans-serif; |     /*font-family: 'Lato', sans-serif;*/ | ||||||
|  | /*     font-weight: normal; */ | ||||||
|     font-size: 50px; |     font-size: 50px; | ||||||
|     color: #999; |     color: #999; | ||||||
| } | } | ||||||
|  | @ -879,7 +891,7 @@ tech-sub-sec h2 { | ||||||
| .dropdown-menu>li>a { | .dropdown-menu>li>a { | ||||||
|     font-size: 13px; |     font-size: 13px; | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .navbar-default .navbar-nav>.active>a, | .navbar-default .navbar-nav>.active>a, | ||||||
|  | @ -898,7 +910,8 @@ tech-sub-sec h2 { | ||||||
|     background: -webkit-linear-gradient(top, #f0f4f7, #fff) no-repeat; |     background: -webkit-linear-gradient(top, #f0f4f7, #fff) no-repeat; | ||||||
|     background: linear-gradient(to bottom, #f0f4f7, #fff) no-repeat; |     background: linear-gradient(to bottom, #f0f4f7, #fff) no-repeat; | ||||||
|     display: flex; |     display: flex; | ||||||
|     font-family: 'Lato', sans-serif; |     /*font-family: 'Lato', sans-serif;*/ | ||||||
|  | /*     font-weight: normal; */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .price-calc-section .text { | .price-calc-section .text { | ||||||
|  | @ -963,7 +976,8 @@ tech-sub-sec h2 { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .price-calc-section .card .title h3 { | .price-calc-section .card .title h3 { | ||||||
|     font-family: 'Lato', sans-serif; |     /*font-family: 'Lato', sans-serif;*/ | ||||||
|  |     font-weight: normal; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .price-calc-section .card .price { | .price-calc-section .card .price { | ||||||
|  | @ -1050,8 +1064,9 @@ tech-sub-sec h2 { | ||||||
| 
 | 
 | ||||||
| .price-calc-section .card .description.input label { | .price-calc-section .card .description.input label { | ||||||
|     font-size: 15px; |     font-size: 15px; | ||||||
|     font-weight: 800; |     font-weight: 700; | ||||||
|     font-family: 'Lato'; |     /*font-weight: 800;*/ | ||||||
|  |     /*font-family: 'Lato';*/ | ||||||
|     margin-bottom: 0; |     margin-bottom: 0; | ||||||
|     width: 40px; |     width: 40px; | ||||||
| } | } | ||||||
|  | @ -1364,7 +1379,8 @@ tech-sub-sec h2 { | ||||||
|         padding: 30px; |         padding: 30px; | ||||||
|     } |     } | ||||||
|     .percent-text { |     .percent-text { | ||||||
|         font-family: 'Lato'; |         /*font-family: 'Lato';*/ | ||||||
|  |         font-weight: normal; | ||||||
|         font-size: 37px; |         font-size: 37px; | ||||||
|         /* text-align: center; */ |         /* text-align: center; */ | ||||||
|     } |     } | ||||||
|  | @ -1402,7 +1418,7 @@ tech-sub-sec h2 { | ||||||
| .network-name { | .network-name { | ||||||
|     text-transform: uppercase; |     text-transform: uppercase; | ||||||
|     font-size: 14px; |     font-size: 14px; | ||||||
|     font-weight: 400; |     font-weight: 300; | ||||||
|     letter-spacing: 2px; |     letter-spacing: 2px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ from .forms import BetaAccessForm | ||||||
| from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate | from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.core.urlresolvers import reverse | from django.core.urlresolvers import reverse | ||||||
|  | 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 | ||||||
| from django.shortcuts import redirect | from django.shortcuts import redirect | ||||||
|  | @ -12,12 +13,14 @@ 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 django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from utils.forms import BillingAddressForm | from utils.forms import BillingAddressForm, UserBillingAddressForm | ||||||
| from hosting.models import HostingOrder | from utils.models import BillingAddress | ||||||
|  | from hosting.models import HostingOrder, HostingBill | ||||||
| from utils.stripe_utils import StripeUtils | from utils.stripe_utils import StripeUtils | ||||||
|  | from datetime import datetime | ||||||
| from membership.models import CustomUser, StripeCustomer | from membership.models import CustomUser, StripeCustomer | ||||||
| from opennebula_api.models import OpenNebulaManager | from opennebula_api.models import OpenNebulaManager | ||||||
| from opennebula_api.serializers import VirtualMachineTemplateSerializer, VMTemplateSerializer | from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer | ||||||
| from datacenterlight.tasks import create_vm_task | from datacenterlight.tasks import create_vm_task | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -423,6 +426,10 @@ class OrderConfirmationView(DetailView): | ||||||
|         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() |         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() | ||||||
|         stripe_utils = StripeUtils() |         stripe_utils = StripeUtils() | ||||||
|         card_details = stripe_utils.get_card_details(customer.stripe_id, request.session.get('token')) |         card_details = stripe_utils.get_card_details(customer.stripe_id, request.session.get('token')) | ||||||
|  |         if not card_details.get('response_object') and not card_details.get('paid'): | ||||||
|  |             msg = card_details.get('error') | ||||||
|  |             messages.add_message(self.request, messages.ERROR, msg, extra_tags='failed_payment') | ||||||
|  |             return HttpResponseRedirect(reverse('datacenterlight:payment') + '#payment_error') | ||||||
|         context = { |         context = { | ||||||
|             'site_url': reverse('datacenterlight:index'), |             'site_url': reverse('datacenterlight:index'), | ||||||
|             'cc_last4': card_details.get('response_object').get('last4'), |             'cc_last4': card_details.get('response_object').get('last4'), | ||||||
|  | @ -438,6 +445,8 @@ class OrderConfirmationView(DetailView): | ||||||
|         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() |         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() | ||||||
|         billing_address_data = request.session.get('billing_address_data') |         billing_address_data = request.session.get('billing_address_data') | ||||||
|         billing_address_id = request.session.get('billing_address') |         billing_address_id = request.session.get('billing_address') | ||||||
|  |         billing_address = BillingAddress.objects.filter( | ||||||
|  |             id=billing_address_id).first() | ||||||
|         vm_template_id = template.get('id', 1) |         vm_template_id = template.get('id', 1) | ||||||
|         final_price = specs.get('price') |         final_price = specs.get('price') | ||||||
| 
 | 
 | ||||||
|  | @ -445,15 +454,12 @@ class OrderConfirmationView(DetailView): | ||||||
|         stripe_utils = StripeUtils() |         stripe_utils = StripeUtils() | ||||||
|         charge_response = stripe_utils.make_charge(amount=final_price, |         charge_response = stripe_utils.make_charge(amount=final_price, | ||||||
|                                                    customer=customer.stripe_id) |                                                    customer=customer.stripe_id) | ||||||
|         charge = charge_response.get('response_object') |  | ||||||
| 
 | 
 | ||||||
|         # Check if the payment was approved |         # Check if the payment was approved | ||||||
|         if not charge: |         if not charge_response.get('response_object') and not charge_response.get('paid'): | ||||||
|             context = {} |             msg = charge_response.get('error') | ||||||
|             context.update({ |             messages.add_message(self.request, messages.ERROR, msg, extra_tags='make_charge_error') | ||||||
|                 'paymentError': charge_response.get('error') |             return HttpResponseRedirect(reverse('datacenterlight:payment') + '#payment_error') | ||||||
|             }) |  | ||||||
|             return render(request, self.payment_template_name, context) |  | ||||||
| 
 | 
 | ||||||
|         charge = charge_response.get('response_object') |         charge = charge_response.get('response_object') | ||||||
|         create_vm_task.delay(vm_template_id, user, specs, template, stripe_customer_id, billing_address_data, |         create_vm_task.delay(vm_template_id, user, specs, template, stripe_customer_id, billing_address_data, | ||||||
|  |  | ||||||
|  | @ -523,6 +523,9 @@ OPENNEBULA_PORT = env('OPENNEBULA_PORT') | ||||||
| # default value is /RPC2 | # default value is /RPC2 | ||||||
| OPENNEBULA_ENDPOINT = env('OPENNEBULA_ENDPOINT') | OPENNEBULA_ENDPOINT = env('OPENNEBULA_ENDPOINT') | ||||||
| 
 | 
 | ||||||
|  | # The public ssh key of the oneadmin user | ||||||
|  | ONEADMIN_USER_SSH_PUBLIC_KEY = env('ONEADMIN_USER_SSH_PUBLIC_KEY') | ||||||
|  | 
 | ||||||
| # dcl email configurations | # dcl email configurations | ||||||
| DCL_TEXT = env('DCL_TEXT') | DCL_TEXT = env('DCL_TEXT') | ||||||
| DCL_SUPPORT_FROM_ADDRESS = env('DCL_SUPPORT_FROM_ADDRESS') | DCL_SUPPORT_FROM_ADDRESS = env('DCL_SUPPORT_FROM_ADDRESS') | ||||||
|  |  | ||||||
|  | @ -14,7 +14,6 @@ def generate_ssh_key_name(): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class HostingUserLoginForm(forms.Form): | class HostingUserLoginForm(forms.Form): | ||||||
| 
 |  | ||||||
|     email = forms.CharField(widget=forms.EmailInput()) |     email = forms.CharField(widget=forms.EmailInput()) | ||||||
|     password = forms.CharField(widget=forms.PasswordInput()) |     password = forms.CharField(widget=forms.PasswordInput()) | ||||||
| 
 | 
 | ||||||
|  | @ -45,7 +44,6 @@ class HostingUserLoginForm(forms.Form): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class HostingUserSignupForm(forms.ModelForm): | class HostingUserSignupForm(forms.ModelForm): | ||||||
| 
 |  | ||||||
|     confirm_password = forms.CharField(widget=forms.PasswordInput()) |     confirm_password = forms.CharField(widget=forms.PasswordInput()) | ||||||
|     password = forms.CharField(widget=forms.PasswordInput()) |     password = forms.CharField(widget=forms.PasswordInput()) | ||||||
| 
 | 
 | ||||||
|  | @ -88,9 +86,8 @@ class UserHostingKeyForm(forms.ModelForm): | ||||||
| 
 | 
 | ||||||
|     def clean(self): |     def clean(self): | ||||||
|         cleaned_data = self.cleaned_data |         cleaned_data = self.cleaned_data | ||||||
|         if not self.cleaned_data.get('name', ''): |         if 'generate' in self.request.POST: | ||||||
|             self.cleaned_data['name'] = generate_ssh_key_name() |             self.cleaned_data['name'] = generate_ssh_key_name() | ||||||
|         if not cleaned_data.get('public_key'): |  | ||||||
|             private_key, public_key = UserHostingKey.generate_keys() |             private_key, public_key = UserHostingKey.generate_keys() | ||||||
|             cleaned_data.update({ |             cleaned_data.update({ | ||||||
|                 'private_key': private_key, |                 'private_key': private_key, | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2017-08-04 18:25+0000\n" | "POT-Creation-Date: 2017-08-11 01:16+0530\n" | ||||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | "Language-Team: LANGUAGE <LL@li.org>\n" | ||||||
|  | @ -393,14 +393,14 @@ msgstr "" | ||||||
| msgid "Delete SSH Key" | msgid "Delete SSH Key" | ||||||
| msgstr "SSH Key löschen" | msgstr "SSH Key löschen" | ||||||
| 
 | 
 | ||||||
| msgid "Do You want to delete this key?" | msgid "Do you want to delete this key?" | ||||||
| msgstr "Möchtest Du den Schlüssel löschen?" | msgstr "Möchtest Du den Schlüssel löschen?" | ||||||
| 
 | 
 | ||||||
| msgid "Show" | msgid "Show" | ||||||
| msgstr "Anzeigen" | msgstr "Anzeigen" | ||||||
| 
 | 
 | ||||||
| msgid "Public ssh key" | msgid "Public SSH Key" | ||||||
| msgstr "" | msgstr "Public SSH Key" | ||||||
| 
 | 
 | ||||||
| msgid "Download" | msgid "Download" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .content-dashboard{ | .content-dashboard{ | ||||||
| 	min-height: calc(100vh - 120px); | 	min-height: calc(100vh - 70px); | ||||||
| 	width: 80%; | 	width: 80%; | ||||||
| 	margin: 0 auto; | 	margin: 0 auto; | ||||||
| 	max-width: 1120px; | 	max-width: 1120px; | ||||||
|  | @ -110,12 +110,16 @@ | ||||||
|     font-weight: 100; |     font-weight: 100; | ||||||
|     color: #999; |     color: #999; | ||||||
| } | } | ||||||
|  | .modal-body .modal-icon { | ||||||
|  |   margin-bottom: 10px; | ||||||
|  | } | ||||||
| .modal-title { | .modal-title { | ||||||
|     margin: 0; |     margin: 0; | ||||||
|     line-height: 1.42857143; |     line-height: 1.42857143; | ||||||
|     font-size: 25px; |     font-size: 25px; | ||||||
|     padding: 0; |     padding: 0; | ||||||
|     font-family: 'Lato', sans-serif; |     /*font-family: 'Lato', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| .modal-text { | .modal-text { | ||||||
|     padding-top: 15px; |     padding-top: 15px; | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
|  * For details, see http://www.apache.org/licenses/LICENSE-2.0. |  * For details, see http://www.apache.org/licenses/LICENSE-2.0. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| @font-face { | /*@font-face { | ||||||
|     font-family: 'Lato-Regular'; |     font-family: 'Lato-Regular'; | ||||||
|     src: url('../fonts/Lato/Lato-Regular.ttf'); |     src: url('../fonts/Lato/Lato-Regular.ttf'); | ||||||
| } | } | ||||||
|  | @ -16,7 +16,7 @@ | ||||||
| @font-face { | @font-face { | ||||||
|     font-family: 'Lato-Light'; |     font-family: 'Lato-Light'; | ||||||
|     src: url('../fonts/Lato/Lato-Light.ttf'); |     src: url('../fonts/Lato/Lato-Light.ttf'); | ||||||
| } | }*/ | ||||||
| 
 | 
 | ||||||
| body, | body, | ||||||
| html { | html { | ||||||
|  | @ -31,8 +31,9 @@ h3, | ||||||
| h4, | h4, | ||||||
| h5, | h5, | ||||||
| h6 { | h6 { | ||||||
|     font-family: 'Lato-Regular', sans-serif; |     /*font-family: 'Lato-Regular', sans-serif;*/ | ||||||
|     font-weight: 300; |     font-family: 'Lato', sans-serif; | ||||||
|  |     /*font-weight: 300;*/ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .topnav { | .topnav { | ||||||
|  | @ -53,7 +54,8 @@ h6 { | ||||||
| .navbar-transparent .navbar-nav>li>a { | .navbar-transparent .navbar-nav>li>a { | ||||||
|     color: #fff; |     color: #fff; | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|     font-family: 'Lato-Regular', sans-serif; |     /*font-family: 'Lato-Regular', sans-serif;*/ | ||||||
|  |     font-weight: normal; | ||||||
| } | } | ||||||
| .navbar-transparent .navbar-nav>li>a:hover { | .navbar-transparent .navbar-nav>li>a:hover { | ||||||
|     color: #fff; |     color: #fff; | ||||||
|  | @ -376,7 +378,8 @@ h6 { | ||||||
|     text-align: center; |     text-align: center; | ||||||
|     font-size: 18px; |     font-size: 18px; | ||||||
|     line-height: 30px; |     line-height: 30px; | ||||||
|     font-family: 'Lato' !important; |     /*font-family: 'Lato' !important;*/ | ||||||
|  |     font-weight: 300 !important; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .sign-up-message a { | .sign-up-message a { | ||||||
|  | @ -454,16 +457,16 @@ h6 { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| footer { | footer { | ||||||
|     padding: 2%; |     padding: 20px; | ||||||
|     background-color: #f8f8f8; |     background-color: #f8f8f8; | ||||||
|     #position: absolute; | /*     position: absolute */ | ||||||
|     right: 0; |     right: 0; | ||||||
|     bottom: 0; |     bottom: 0; | ||||||
|     left: 0; |     left: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| p.copyright { | p.copyright { | ||||||
|     margin: 15px 0 0; |     margin: 14px 0 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| a#forgotpassword { | a#forgotpassword { | ||||||
|  | @ -488,7 +491,8 @@ a.unlink:hover { | ||||||
| 
 | 
 | ||||||
| /***** DCL payment page **********/ | /***** DCL payment page **********/ | ||||||
| .dcl-order-container { | .dcl-order-container { | ||||||
|     font-family: Lato; |     /*font-family: Lato;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .dcl-order-table-header { | .dcl-order-table-header { | ||||||
|  | @ -547,11 +551,16 @@ a.unlink:hover { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .card-warning-content { | .card-warning-content { | ||||||
|     font-family: Lato; |     /*font-family: Lato;*/ | ||||||
|  |     font-weight: 300; | ||||||
|     border: 1px solid #a1a1a1; |     border: 1px solid #a1a1a1; | ||||||
|     border-radius: 3px; |     border-radius: 3px; | ||||||
|     padding: 5px; |     padding: 5px; | ||||||
| } | } | ||||||
|  | .card-warning-error { | ||||||
|  |     border: 1px solid #EB4D5C; | ||||||
|  |     color: #EB4D5C; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| .card-warning-addtional-margin { | .card-warning-addtional-margin { | ||||||
|     margin-top: 15px; |     margin-top: 15px; | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
| 	font-size: 14px; | 	font-size: 14px; | ||||||
| 	padding-left: 0; | 	padding-left: 0; | ||||||
| 	margin-bottom: 30px; | 	margin-bottom: 30px; | ||||||
|   font-family: 'Lato'; |   	font-family: Lato, sans-serif; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* ssh_keys_choice */ | /* ssh_keys_choice */ | ||||||
| .h1-thin { | .h1-thin { | ||||||
|     font-family: Lato, sans-serif; |     /*font-family: Lato, sans-serif;*/ | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
|     font-size: 32px; |     font-size: 32px; | ||||||
| } | } | ||||||
|  | @ -10,12 +10,12 @@ | ||||||
| } | } | ||||||
| .dashboard-choice-container .page-header p { | .dashboard-choice-container .page-header p { | ||||||
|     font-size: 16px; |     font-size: 16px; | ||||||
|     font-family: Lato, sans-serif; |     /*font-family: Lato, sans-serif;*/ | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
| } | } | ||||||
| .dashboard-choice-container h2 { | .dashboard-choice-container h2 { | ||||||
|     font-family: Lato, sans-serif; |     /*font-family: Lato, sans-serif; | ||||||
|     font-weight: 400; |     font-weight: 400;*/ | ||||||
|     font-size: 22px; |     font-size: 22px; | ||||||
|     margin-top: 0; |     margin-top: 0; | ||||||
| } | } | ||||||
|  | @ -26,7 +26,7 @@ | ||||||
| } | } | ||||||
| .choice-container p{ | .choice-container p{ | ||||||
|     font-size: 18px; |     font-size: 18px; | ||||||
|     font-family: Lato, sans-serif; |     /*font-family: Lato, sans-serif;*/ | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
| } | } | ||||||
| .choice-container-top { | .choice-container-top { | ||||||
|  | @ -119,7 +119,7 @@ | ||||||
|     color: #717274; |     color: #717274; | ||||||
|     font-size: 16px; |     font-size: 16px; | ||||||
|     font-weight: 300; |     font-weight: 300; | ||||||
|     font-family: 'Lato'; |     /*font-family: 'Lato';*/ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .borderless tbody:before { | .borderless tbody:before { | ||||||
|  | @ -195,7 +195,8 @@ | ||||||
|     border-bottom: 1px solid grey; |     border-bottom: 1px solid grey; | ||||||
|     box-shadow: none; |     box-shadow: none; | ||||||
|     border-radius: 0; |     border-radius: 0; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     padding-left: 0; |     padding-left: 0; | ||||||
| } | } | ||||||
|  | @ -203,57 +204,58 @@ | ||||||
| .form_key_name::-webkit-input-placeholder{ | .form_key_name::-webkit-input-placeholder{ | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight:100; |     font-weight:100; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| .form_key_name::-moz-input-placeholder{ | .form_key_name::-moz-input-placeholder{ | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight:200; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     font-weight: 300; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| .form_key_name:-moz-input-placeholder{ | .form_key_name:-moz-input-placeholder{ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight:200; |  | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| .form_key_name:-ms-input-placeholder { | .form_key_name:-ms-input-placeholder { | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|     font-weight:200; |     font-weight: 300; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .form_public_key::-webkit-input-placeholder{ | .form_public_key::-webkit-input-placeholder{ | ||||||
|     position: relative; |     position: relative; | ||||||
|     top: 110px; |     top: 110px; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight: 200; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     font-weight: 300; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| .form_public_key::-moz-input-placeholder{ | .form_public_key::-moz-input-placeholder{ | ||||||
|     position: relative; |     position: relative; | ||||||
|     top: 110px; |     top: 110px; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|     font-weight:200; |     font-weight: 300; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| .form_public_key:-moz-input-placeholder{ | .form_public_key:-moz-input-placeholder{ | ||||||
|     position: relative; |     position: relative; | ||||||
|     top: 110px; |     top: 110px; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight:200; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     font-weight: 300; | ||||||
| } | } | ||||||
| .form_public_key:-ms-input-placeholder { | .form_public_key:-ms-input-placeholder { | ||||||
|     position: relative; |     position: relative; | ||||||
|     top: 110px; |     top: 110px; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight:200; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     font-weight: 300; | ||||||
| } | } | ||||||
| .underform-contaner{ | .underform-contaner{ | ||||||
|     margin-bottom: 20px; |     margin-bottom: 20px; | ||||||
|  | @ -273,7 +275,8 @@ | ||||||
|     } |     } | ||||||
| } | } | ||||||
| .underform-contaner h4{ | .underform-contaner h4{ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
| } | } | ||||||
| .underform-contaner button{ | .underform-contaner button{ | ||||||
|     /* font-family: Lato; */ |     /* font-family: Lato; */ | ||||||
|  | @ -287,13 +290,16 @@ | ||||||
|     color: #fff; |     color: #fff; | ||||||
| } | } | ||||||
| .control-label{ | .control-label{ | ||||||
|     font-family: 'Lato-Light', sans-serif; |     /*font-family: 'Lato-Light', sans-serif;*/ | ||||||
|  |     font-weight: 300; | ||||||
|     font-size: 20px; |     font-size: 20px; | ||||||
|     font-weight:200; |  | ||||||
| } | } | ||||||
| .form-ssh h3{ | .form-ssh h3{ | ||||||
|     margin-bottom: 40px; |     margin-bottom: 40px; | ||||||
| } | } | ||||||
|  | .key_contain { | ||||||
|  |     word-break: break-all; | ||||||
|  | } | ||||||
| .custom_form_button{ | .custom_form_button{ | ||||||
|     border-radius: 0; |     border-radius: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -59,7 +59,6 @@ | ||||||
|                         {% csrf_token %} |                         {% csrf_token %} | ||||||
|                         {% bootstrap_field field show_label=False type='fields'%} |                         {% bootstrap_field field show_label=False type='fields'%} | ||||||
|                         {% endfor %} |                         {% endfor %} | ||||||
|                         {% bootstrap_form_errors form type='non_fields'%} |  | ||||||
|                     </form> |                     </form> | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="col-xs-12 col-sm-7 col-md-6 creditcard-box dcl-creditcard"> |                 <div class="col-xs-12 col-sm-7 col-md-6 creditcard-box dcl-creditcard"> | ||||||
|  | @ -86,12 +85,28 @@ | ||||||
|                             </form> |                             </form> | ||||||
|                             <div class="row"> |                             <div class="row"> | ||||||
|                                 <div class="col-xs-12"> |                                 <div class="col-xs-12"> | ||||||
|  |                                         {% if not messages and not form.non_field_errors %} | ||||||
|                                             <p class="card-warning-content card-warning-addtional-margin"> |                                             <p class="card-warning-content card-warning-addtional-margin"> | ||||||
|                                                 {% blocktrans %} |                                                 {% blocktrans %} | ||||||
|                                                 You are not making any payment yet. After submitting your card |                                                 You are not making any payment yet. After submitting your card | ||||||
|                                                 information, you will be taken to the Confirm Order Page. |                                                 information, you will be taken to the Confirm Order Page. | ||||||
|                                                 {% endblocktrans %} |                                                 {% endblocktrans %} | ||||||
|                                             </p> |                                             </p> | ||||||
|  |                                         {% endif %} | ||||||
|  |                                         <div id='payment_error'> | ||||||
|  |                                             {% for message in messages %} | ||||||
|  |                                                 {% if 'failed_payment' or 'make_charge_error' in message.tags %} | ||||||
|  |                                                  <ul class="list-unstyled"><li> | ||||||
|  |                                                      <p class="card-warning-content card-warning-error">{{ message|safe }}</p> | ||||||
|  |                                                 </li></ul> | ||||||
|  |                                                 {% endif %} | ||||||
|  |                                             {% endfor %} | ||||||
|  |                                             {% for error in form.non_field_errors %} | ||||||
|  |                                                 <p class="card-warning-content card-warning-error"> | ||||||
|  |                                                     {{ error|escape }} | ||||||
|  |                                                 </p> | ||||||
|  |                                             {% endfor %} | ||||||
|  |                                         </div> | ||||||
|                                     </div> |                                     </div> | ||||||
|                                 <div class="col-xs-12"> |                                 <div class="col-xs-12"> | ||||||
|                                     <div class="col-xs-6 pull-right"> |                                     <div class="col-xs-6 pull-right"> | ||||||
|  | @ -130,12 +145,29 @@ | ||||||
|                                 <div id="card-errors" role="alert"></div> |                                 <div id="card-errors" role="alert"></div> | ||||||
|                                 <div class="row"> |                                 <div class="row"> | ||||||
|                                     <div class="col-xs-12"> |                                     <div class="col-xs-12"> | ||||||
|  |                                         {% if not messages and not form.non_field_errors %} | ||||||
|                                             <p class="card-warning-content"> |                                             <p class="card-warning-content"> | ||||||
|                                                 {% blocktrans %} |                                                 {% blocktrans %} | ||||||
|                                                 You are not making any payment yet. After submitting your card |                                                 You are not making any payment yet. After submitting your card | ||||||
|                                                 information, you will be taken to the Confirm Order Page. |                                                 information, you will be taken to the Confirm Order Page. | ||||||
|                                                 {% endblocktrans %} |                                                 {% endblocktrans %} | ||||||
|                                             </p> |                                             </p> | ||||||
|  |                                         {% endif %} | ||||||
|  |                                         <div id='payment_error'> | ||||||
|  |                                             {% for message in messages %} | ||||||
|  |                                                 {% if 'failed_payment' or 'make_charge_error' in message.tags %} | ||||||
|  |                                                  <ul class="list-unstyled"><li> | ||||||
|  |                                                      <p class="card-warning-content card-warning-error">{{ message|safe }}</p> | ||||||
|  |                                                 </li></ul> | ||||||
|  |                                                 {% endif %} | ||||||
|  |                                             {% endfor %} | ||||||
|  | 
 | ||||||
|  |                                             {% for error in form.non_field_errors %} | ||||||
|  |                                                 <p class="card-warning-content card-warning-error"> | ||||||
|  |                                                     {{ error|escape }} | ||||||
|  |                                                 </p> | ||||||
|  |                                             {% endfor %} | ||||||
|  |                                         </div> | ||||||
|                                     </div> |                                     </div> | ||||||
|                                     <div class="col-xs-12"> |                                     <div class="col-xs-12"> | ||||||
|                                         <div class="col-xs-6 pull-right"> |                                         <div class="col-xs-6 pull-right"> | ||||||
|  | @ -150,15 +182,6 @@ | ||||||
|                                         <p class="payment-errors"></p> |                                         <p class="payment-errors"></p> | ||||||
|                                     </div> |                                     </div> | ||||||
|                                 </div> |                                 </div> | ||||||
|                                 {% if paymentError %} |  | ||||||
|                                 <div class="row"> |  | ||||||
|                                     <div class="col-xs-12"> |  | ||||||
|                                         <p> |  | ||||||
|                                             {% bootstrap_alert paymentError alert_type='danger' %} |  | ||||||
|                                         </p> |  | ||||||
|                                     </div> |  | ||||||
|                                 </div> |  | ||||||
|                                 {% endif %} |  | ||||||
|                             </form> |                             </form> | ||||||
| 
 | 
 | ||||||
|                             {% endif %} |                             {% endif %} | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ | ||||||
|                                     <div class="modal-body"> |                                     <div class="modal-body"> | ||||||
|                                      <div class="modal-icon"><i class="fa fa-trash" aria-hidden="true"></i></div> |                                      <div class="modal-icon"><i class="fa fa-trash" aria-hidden="true"></i></div> | ||||||
|                                       <h4 class="modal-title" id="ModalLabel">{% trans "Delete SSH Key"%}</h4> |                                       <h4 class="modal-title" id="ModalLabel">{% trans "Delete SSH Key"%}</h4> | ||||||
|                                         <p class="modal-text">{% trans "Do You want to delete this key?"%}</p> |                                         <p class="modal-text">{% trans "Do you want to delete this key?"%}</p> | ||||||
|                                         <form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}"> |                                         <form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}"> | ||||||
|                                             {% csrf_token %} |                                             {% csrf_token %} | ||||||
|                                             <div class="modal-footer"> |                                             <div class="modal-footer"> | ||||||
|  | @ -77,8 +77,8 @@ | ||||||
|                                         </button> |                                         </button> | ||||||
|                                     </div> |                                     </div> | ||||||
|                                     <div class="modal-body"> |                                     <div class="modal-body"> | ||||||
|                                         <h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public ssh key" %}</h4> |                                         <h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public SSH key" %}</h4> | ||||||
|                                         <p style="margin-top: 10px;">{{ user_key.public_key }}</p> |                                         <p class="key_contain" style="margin-top: 10px;">{{ user_key.public_key }}</p> | ||||||
|                                         <div class="modal-footer"> |                                         <div class="modal-footer"> | ||||||
|                                         </div> |                                         </div> | ||||||
|                                     </div> |                                     </div> | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| 		<div class="row"> | 		<div class="row"> | ||||||
| 			<div class="col-xs-12  container-table"> | 			<div class="col-xs-12  container-table"> | ||||||
| 				<table class="table borderless table-hover"> | 				<table class="table borderless table-hover"> | ||||||
| 				<h3 class="pull-left"><i class="fa fa-server fa-separate" aria-hidden="true"></i> {% trans "Virtual Machines"%} </h3> | 				<h3 class="pull-left"><i class="fa fa-server fa-separate" aria-hidden="true"></i> {% trans "Virtual Machines"%}</h3> | ||||||
|                 <div class="col-md-12"> |                 <div class="col-md-12"> | ||||||
|                     <br/> |                     <br/> | ||||||
|                     {% if messages %} |                     {% if messages %} | ||||||
|  | @ -60,8 +60,8 @@ | ||||||
| 					</tr> | 					</tr> | ||||||
| 					{% endfor %} | 					{% endfor %} | ||||||
| 				</tbody> | 				</tbody> | ||||||
| 				</table> |  | ||||||
|                 {% endif %} |                 {% endif %} | ||||||
|  |                 </table> | ||||||
| 
 | 
 | ||||||
| 			    {% if is_paginated %} | 			    {% if is_paginated %} | ||||||
| 			        <div class="pagination"> | 			        <div class="pagination"> | ||||||
|  |  | ||||||
|  | @ -342,6 +342,15 @@ class SSHKeyDeleteView(LoginRequiredMixin, DeleteView): | ||||||
|     success_url = reverse_lazy('hosting:ssh_keys') |     success_url = reverse_lazy('hosting:ssh_keys') | ||||||
|     model = UserHostingKey |     model = UserHostingKey | ||||||
| 
 | 
 | ||||||
|  |     def get_object(self, queryset=None): | ||||||
|  |         """ Hook to ensure UserHostingKey object is owned by request.user. | ||||||
|  |             We reply with a Http404 if the user is not the owner of the key. | ||||||
|  |         """ | ||||||
|  |         obj = super(SSHKeyDeleteView, self).get_object() | ||||||
|  |         if not obj.user == self.request.user: | ||||||
|  |             raise Http404 | ||||||
|  |         return obj | ||||||
|  | 
 | ||||||
|     def delete(self, request, *args, **kwargs): |     def delete(self, request, *args, **kwargs): | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         manager = OpenNebulaManager() |         manager = OpenNebulaManager() | ||||||
|  | @ -547,8 +556,9 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|             customer = StripeCustomer.get_or_create(email=owner.email, |             customer = StripeCustomer.get_or_create(email=owner.email, | ||||||
|                                                     token=token) |                                                     token=token) | ||||||
|             if not customer: |             if not customer: | ||||||
|                 form.add_error("__all__", "Invalid credit card") |                 msg = _("Invalid credit card") | ||||||
|                 return self.render_to_response(self.get_context_data(form=form)) |                 messages.add_message(self.request, messages.ERROR, msg, extra_tags='make_charge_error') | ||||||
|  |                 return HttpResponseRedirect(reverse('hosting:payment') + '#payment_error') | ||||||
| 
 | 
 | ||||||
|             # Create Billing Address |             # Create Billing Address | ||||||
|             billing_address = form.save() |             billing_address = form.save() | ||||||
|  | @ -557,15 +567,12 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|             stripe_utils = StripeUtils() |             stripe_utils = StripeUtils() | ||||||
|             charge_response = stripe_utils.make_charge(amount=final_price, |             charge_response = stripe_utils.make_charge(amount=final_price, | ||||||
|                                                        customer=customer.stripe_id) |                                                        customer=customer.stripe_id) | ||||||
|             charge = charge_response.get('response_object') |  | ||||||
| 
 | 
 | ||||||
|             # Check if the payment was approved |             # Check if the payment was approved | ||||||
|             if not charge: |             if not charge_response.get('response_object') and not charge_response.get('paid'): | ||||||
|                 context.update({ |                 msg = charge_response.get('error') | ||||||
|                     'paymentError': charge_response.get('error'), |                 messages.add_message(self.request, messages.ERROR, msg, extra_tags='make_charge_error') | ||||||
|                     'form': form |                 return HttpResponseRedirect(reverse('hosting:payment') + '#payment_error') | ||||||
|                 }) |  | ||||||
|                 return render(request, self.template_name, context) |  | ||||||
| 
 | 
 | ||||||
|             charge = charge_response.get('response_object') |             charge = charge_response.get('response_object') | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ REGISTRATION_MESSAGE = {'subject': "Validation mail", | ||||||
|                         'from': 'test@test.com'} |                         'from': 'test@test.com'} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_anonymous_user_instance(): | def get_anonymous_user_instance(CustomUser): | ||||||
|     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)) | ||||||
| 
 | 
 | ||||||
|  | @ -173,7 +173,6 @@ class StripeCustomer(models.Model): | ||||||
|             Check if there is a registered stripe customer with that email |             Check if there is a registered stripe customer with that email | ||||||
|             or create a new one |             or create a new one | ||||||
|         """ |         """ | ||||||
|         stripe_customer = None |  | ||||||
|         try: |         try: | ||||||
|             stripe_utils = StripeUtils() |             stripe_utils = StripeUtils() | ||||||
|             stripe_customer = cls.objects.get(user__email=email) |             stripe_customer = cls.objects.get(user__email=email) | ||||||
|  | @ -189,7 +188,7 @@ class StripeCustomer(models.Model): | ||||||
|             user = CustomUser.objects.get(email=email) |             user = CustomUser.objects.get(email=email) | ||||||
| 
 | 
 | ||||||
|             stripe_utils = StripeUtils() |             stripe_utils = StripeUtils() | ||||||
|             stripe_data = stripe_utils.create_customer(token, email) |             stripe_data = stripe_utils.create_customer(token, email, user.name) | ||||||
|             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') | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								utils/migrations/0006_auto_20170810_1742.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								utils/migrations/0006_auto_20170810_1742.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # Generated by Django 1.9.4 on 2017-08-10 17:42 | ||||||
|  | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('utils', '0005_auto_20170322_1443'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='billingaddress', | ||||||
|  |             name='cardholder_name', | ||||||
|  |             field=models.CharField(default='', max_length=100), | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='userbillingaddress', | ||||||
|  |             name='cardholder_name', | ||||||
|  |             field=models.CharField(default='', max_length=100), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
|  | @ -11,7 +11,7 @@ def handleStripeError(f): | ||||||
|             'error': None |             'error': None | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         common_message = "Currently its not possible to make payments." |         common_message = "Currently it's not possible to make payments." | ||||||
|         try: |         try: | ||||||
|             response_object = f(*args, **kwargs) |             response_object = f(*args, **kwargs) | ||||||
|             response = { |             response = { | ||||||
|  | @ -90,12 +90,12 @@ class StripeUtils(object): | ||||||
|     def check_customer(self, id, user, token): |     def check_customer(self, id, user, token): | ||||||
|         customers = self.stripe.Customer.all() |         customers = self.stripe.Customer.all() | ||||||
|         if not customers.get('data'): |         if not customers.get('data'): | ||||||
|             customer = self.create_customer(token, user.email) |             customer = self.create_customer(token, user.email, user.name) | ||||||
|         else: |         else: | ||||||
|             try: |             try: | ||||||
|                 customer = stripe.Customer.retrieve(id) |                 customer = stripe.Customer.retrieve(id) | ||||||
|             except stripe.InvalidRequestError: |             except stripe.InvalidRequestError: | ||||||
|                 customer = self.create_customer(token, user.email) |                 customer = self.create_customer(token, user.email, user.name) | ||||||
|                 user.stripecustomer.stripe_id = customer.get('response_object').get('id') |                 user.stripecustomer.stripe_id = customer.get('response_object').get('id') | ||||||
|                 user.stripecustomer.save() |                 user.stripecustomer.save() | ||||||
|         return customer |         return customer | ||||||
|  | @ -107,11 +107,12 @@ class StripeUtils(object): | ||||||
|         return customer |         return customer | ||||||
| 
 | 
 | ||||||
|     @handleStripeError |     @handleStripeError | ||||||
|     def create_customer(self, token, email): |     def create_customer(self, token, email, name=None): | ||||||
| 
 |         if name is None or name.strip() == "": | ||||||
|  |             name = email | ||||||
|         customer = self.stripe.Customer.create( |         customer = self.stripe.Customer.create( | ||||||
|             source=token, |             source=token, | ||||||
|             description='description for testing', |             description=name, | ||||||
|             email=email |             email=email | ||||||
|         ) |         ) | ||||||
|         return customer |         return customer | ||||||
|  |  | ||||||
|  | @ -3,6 +3,9 @@ from django.test import Client | ||||||
| from django.http.request import HttpRequest | from django.http.request import HttpRequest | ||||||
| 
 | 
 | ||||||
| from model_mommy import mommy | from model_mommy import mommy | ||||||
|  | from utils.stripe_utils import StripeUtils | ||||||
|  | import stripe | ||||||
|  | from django.conf import settings | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BaseTestCase(TestCase): | class BaseTestCase(TestCase): | ||||||
|  | @ -11,7 +14,6 @@ class BaseTestCase(TestCase): | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
| 
 |  | ||||||
|         # Password |         # Password | ||||||
|         self.dummy_password = 'test_password' |         self.dummy_password = 'test_password' | ||||||
| 
 | 
 | ||||||
|  | @ -83,3 +85,35 @@ class BaseTestCase(TestCase): | ||||||
|         view.kwargs = kwargs |         view.kwargs = kwargs | ||||||
|         view.config = None |         view.config = None | ||||||
|         return view |         return view | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestStripeCustomerDescription(TestCase): | ||||||
|  |     """ | ||||||
|  |     A class to test setting the description field of the stripe customer | ||||||
|  |     https://stripe.com/docs/api#metadata | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     def setUp(self): | ||||||
|  |         self.dummy_password = 'test_password' | ||||||
|  |         self.dummy_email = 'test@ungleich.ch' | ||||||
|  |         self.customer = mommy.make('membership.CustomUser') | ||||||
|  |         self.customer.set_password(self.dummy_password) | ||||||
|  |         self.customer.email = self.dummy_email | ||||||
|  |         self.customer.save() | ||||||
|  |         stripe.api_key = settings.STRIPE_API_PRIVATE_KEY | ||||||
|  | 
 | ||||||
|  |     def test_creating_stripe_customer(self): | ||||||
|  |         test_name = "Monty Python" | ||||||
|  |         token = stripe.Token.create( | ||||||
|  |             card={ | ||||||
|  |                 "number": '4111111111111111', | ||||||
|  |                 "exp_month": 12, | ||||||
|  |                 "exp_year": 2022, | ||||||
|  |                 "cvc": '123' | ||||||
|  |             }, | ||||||
|  |         ) | ||||||
|  |         stripe_utils = StripeUtils() | ||||||
|  |         stripe_data = stripe_utils.create_customer(token.id, self.customer.email, test_name) | ||||||
|  |         self.assertEqual(stripe_data.get('error'), None) | ||||||
|  |         customer_data = stripe_data.get('response_object') | ||||||
|  |         self.assertEqual(customer_data.description, test_name) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue