merge master

This commit is contained in:
Arvind Tiwari 2017-09-28 18:23:48 +05:30
commit b65bc3f1f5
16 changed files with 614 additions and 321 deletions

View file

@ -4,7 +4,7 @@ Next:
* #3730: [dcl] Refactor price parameter passed in the DCL flow * #3730: [dcl] Refactor price parameter passed in the DCL flow
* #3807: [dcl] Remove PricingView as it is no more used * #3807: [dcl] Remove PricingView as it is no more used
* #3813: [hosting] JS error in create ssh key page * #3813: [hosting] JS error in create ssh key page
* #3756: [dcl] Update landing calculator and billing info page
1.2.3: 2017-09-25 1.2.3: 2017-09-25
* #3484: [dcl, hosting] Refactored account activation, password reset, VM order and cancellation email * #3484: [dcl, hosting] Refactored account activation, password reset, VM order and cancellation email
* #3731: [dcl, hosting] Added cdist ssh key handler * #3731: [dcl, hosting] Added cdist ssh key handler

View file

@ -65,24 +65,6 @@ msgstr "Bitte gib einen Wert von 10 bis 200 ein."
msgid "GB Storage (SSD)" msgid "GB Storage (SSD)"
msgstr "GB Storage (SSD)" msgstr "GB Storage (SSD)"
msgid "Name"
msgstr ""
msgid "Your Name"
msgstr "Dein Name"
msgid "Please enter your name."
msgstr "Bitte gib Deinen Namen ein."
msgid "Email"
msgstr "E-Mail-Adresse"
msgid "Your Email"
msgstr "Deine E-Mail"
msgid "Please enter a valid email address."
msgstr "Bitte gib eine gültige E-Mailadresse ein."
msgid "Continue" msgid "Continue"
msgstr "Weiter" msgstr "Weiter"
@ -95,6 +77,18 @@ msgstr "Vielen Dank für Deine Nachricht."
msgid "Get in touch with us!" msgid "Get in touch with us!"
msgstr "Sende uns eine Nachricht." msgstr "Sende uns eine Nachricht."
msgid "Name"
msgstr ""
msgid "Please enter your name."
msgstr "Bitte gib Deinen Namen ein."
msgid "Email"
msgstr "E-Mail-Adresse"
msgid "Please enter a valid email address."
msgstr "Bitte gib eine gültige E-Mailadresse ein."
msgid "Message" msgid "Message"
msgstr "Nachricht" msgstr "Nachricht"
@ -151,6 +145,15 @@ msgstr ""
"Adressleiste deines Browsers.<br/>\n" "Adressleiste deines Browsers.<br/>\n"
"%(base_url)s%(activation_link)s\n" "%(base_url)s%(activation_link)s\n"
#, python-format
msgid ""
"Your account details are as follows:<br/><br/>\n"
"Username : Your email address<br/>\n"
"Password : %(account_details)s<br/><br/>\n"
"You can reset your password here:\n"
"%(base_url)s%(reset_password_url)s\n"
msgstr ""
#, python-format #, python-format
msgid "" msgid ""
"You can activate your Data Center Light account by clicking here.\n" "You can activate your Data Center Light account by clicking here.\n"
@ -163,6 +166,17 @@ msgstr ""
"den folgenden Link in die Adressleiste deines Browsers.\n" "den folgenden Link in die Adressleiste deines Browsers.\n"
"%(base_url)s%(activation_link)s\n" "%(base_url)s%(activation_link)s\n"
#, python-format
msgid ""
"Your account details are as follows:\n"
"\n"
"Username : Your email address\n"
"Password : %(account_details)s\n"
"\n"
"You can reset your password here:\n"
"%(base_url)s%(reset_password_url)s\n"
msgstr ""
msgid "Home" msgid "Home"
msgstr "Home" msgstr "Home"
@ -264,6 +278,45 @@ msgstr "Kontaktiere uns"
msgid "Switzerland " msgid "Switzerland "
msgstr "Schweiz " msgstr "Schweiz "
msgid "Welcome back"
msgstr "Willkommen zurück"
msgid ""
"Review your billing address and card details and proceed to make payment."
msgstr ""
"Überprüfe die Rechnungsadresse und Kreditkartendaten und fahre mit der "
"Zahlung fort."
msgid "Log in"
msgstr "Anmelden"
msgid ""
"Already signed up?<br>By logging in you can retrieve saved billing "
"information."
msgstr ""
"Bereits eingeloggt? Nach der Anmeldung kannst Du gespeicherte "
"Rechnungsinformationen abrufen."
msgid "LOGIN"
msgstr "ANMELDEN"
msgid "Don't have an account yet?"
msgstr "Besitzt du kein Benutzerkonto?"
msgid "You can sign up by filling in the information below."
msgstr ""
"Du kannst Dich anmelden, indem Du die die untenstehenden Informationen "
"ausfüllst."
msgid "Forgot password?"
msgstr "Passwort vergessen?"
msgid "Sign up"
msgstr "Registrieren"
msgid "Billing Address"
msgstr "Rechnungsadresse"
msgid "Your Order" msgid "Your Order"
msgstr "Deine Bestellung" msgstr "Deine Bestellung"
@ -288,23 +341,15 @@ msgstr "inkl. Mehrwertsteuer"
msgid "Month" msgid "Month"
msgstr "Monat" msgstr "Monat"
msgid "Billing Address"
msgstr "Rechnungsadresse"
msgid "Credit Card" msgid "Credit Card"
msgstr "Kreditkarte" msgstr "Kreditkarte"
msgid "" msgid ""
"\n" "Please fill in your credit card information below. We are using <a href="
" Please fill in your credit card information " "\"https://stripe.com\" target=\"_blank\">Stripe</a> for payment and do not "
"below. We are using <a\n" "store your information in our database."
" href=\"https://stripe.com\" target="
"\"_blank\">Stripe</a> for payment and do not store\n"
" your information in our database.\n"
" "
msgstr "" msgstr ""
"\n" "Bitte fülle Deine Kreditkarteninformationen unten aus. Wir nutzen <a href="
"Bitte füll Deine Kreditkarteninformationen unten aus. Wir nutzen <a href="
"\"https://stripe.com\" target=\"_blank\">Stripe</a> für die Bezahlung und " "\"https://stripe.com\" target=\"_blank\">Stripe</a> für die Bezahlung und "
"speichern keine Informationen in unserer Datenbank." "speichern keine Informationen in unserer Datenbank."
@ -330,6 +375,13 @@ msgstr ""
msgid "Card Type" msgid "Card Type"
msgstr "Kartentyp" msgstr "Kartentyp"
msgid ""
"You are not making any payment yet. After placing your order, you will be "
"taken to the Submit Payment Page."
msgstr ""
"Es wird noch keine Bezahlung vorgenommen. Die Bezahlung wird erst ausgelöst, "
"nachdem Du die Bestellung auf der nächsten Seite bestätigt hast."
msgid "Processing" msgid "Processing"
msgstr "Weiter" msgstr "Weiter"
@ -347,6 +399,36 @@ msgstr ""
msgid "Place order" msgid "Place order"
msgstr "Bestellen" msgstr "Bestellen"
msgid "Processing..."
msgstr "Abarbeitung..."
msgid "Hold tight, we are processing your request"
msgstr "Bitte warten - wir verbeiten Deine Anfrage gerade"
msgid "Some problem encountered. Please try again later."
msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal."
msgid "We are cutting down the costs significantly!"
msgstr "Wir sorgen dafür, dass die Kosten für Dich signifikant abnehmen"
msgid "Order Now!"
msgstr "Bestelle jetzt!"
msgid ""
"Our VMs are hosted in Glarus, Switzerland, and our website is currently "
"running in BETA mode. If you want more information that you did not find on "
"our website, or if your order is more detailed, or if you encounter any "
"technical hiccups, please contact us at support@datacenterlight.ch, our team "
"will get in touch with you asap."
msgstr ""
"Unsere VMs werden in der Schweiz im Kanton Glarus gehostet und befinden sich "
"zur Zeit noch in der BETA-Phase. Möchtest du mehr über uns erfahren und hast "
"auf unserer Website nicht genügend Informationen gefunden? Möchtest eine "
"detailliertere Bestellung aufgeben? Bist du auf technische Probleme "
"gestossen, die du uns mitteilen möchtest? Dann zögere nicht und kontaktiere "
"uns unter support@datacenterlight.ch. Unser Team wird sich umgehend um dein "
"Anliegen kümmern!"
msgid "Thank you for order! Our team will contact you via email" msgid "Thank you for order! Our team will contact you via email"
msgstr "" msgstr ""
"Vielen Dank für die Bestellung. Unser Team setzt sich sobald wie möglich mit " "Vielen Dank für die Bestellung. Unser Team setzt sich sobald wie möglich mit "
@ -440,11 +522,38 @@ msgstr "Ungültige RAM-Grösse"
msgid "Invalid storage size" msgid "Invalid storage size"
msgstr "Ungültige Speicher-Grösse" msgstr "Ungültige Speicher-Grösse"
msgid "is not a proper name" msgid "Error."
msgstr "ist kein gültiger Name" msgstr ""
msgid "is not a proper email" msgid ""
msgstr "ist keine gültige E-Mailadresse" "There was a payment related error. On close of this popup, you will be "
"redirected back to the payment page."
msgstr ""
msgid "Thank you for the order."
msgstr "Danke für Deine Bestellung."
msgid ""
"Your VM will be up and running in a few moments. We will send you a "
"confirmation email as soon as it is ready."
msgstr ""
"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
"auf sie zugreifen kannst."
#~ msgid "Email Address"
#~ msgstr "E-Mail-Adresse"
#~ msgid "is not a proper name"
#~ msgstr "ist kein gültiger Name"
#~ msgid "is not a proper email"
#~ msgstr "ist keine gültige E-Mailadresse"
#~ msgid "Your Name"
#~ msgstr "Dein Name"
#~ msgid "Your Email"
#~ msgstr "Deine E-Mail"
msgid "Confirm Order" msgid "Confirm Order"
msgstr "Bestellung Bestätigen" msgstr "Bestellung Bestätigen"

View file

@ -80,43 +80,6 @@
<!--<div class="description check-ip"> <!--<div class="description check-ip">
<input type="checkbox" name="ipv6"> Ipv6 Only<br> <input type="checkbox" name="ipv6"> Ipv6 Only<br>
</div>--> </div>-->
<div class="form-group">
<div class="description input justify-center">
<label for="name" class="control-label">{% trans "Name"%}</label>
<input type="text" name="name" class="form-control" placeholder="{% trans 'Your Name'%}"
data-minlength="3" data-error="{% trans 'Please enter your name.' %}" required>
</div>
<div class="help-block with-errors">
{% for message in messages %}
{% if 'name' in message.tags %}
<ul class="list-unstyled">
<li>
{{ message|safe }}
</li>
</ul>
{% endif %}
{% endfor %}
</div>
</div>
<div class="form-group">
<div class="description input justify-center">
<label for="email" class="control-label">{% trans "Email"%}</label>
<input name="email" type="email" pattern="^[^@\s]+@([^@\s]+\.)+[^@\s]+$" class="form-control"
placeholder="{% trans 'Your Email' %}"
data-error="{% trans 'Please enter a valid email address.' %}" required>
</div>
<div class="help-block with-errors">
{% for message in messages %}
{% if 'email' in message.tags %}
<ul class="list-unstyled">
<li>
{{ message|safe }}
</li>
</ul>
{% endif %}
{% endfor %}
</div>
</div>
</div> </div>
<input type="submit" class="btn btn-primary disabled" value="{% trans 'Continue' %}"></input> <input type="submit" class="btn btn-primary disabled" value="{% trans 'Continue' %}"></input>
</form> </form>

View file

@ -11,4 +11,14 @@ You can also copy and paste the following link into the address bar of your brow
to activate your Data Center Light account.<br/> to activate your Data Center Light account.<br/>
{{base_url}}{{activation_link}} {{base_url}}{{activation_link}}
{% endblocktrans %} {% endblocktrans %}
{% if account_details %}
{% url 'hosting:reset_password' as reset_password_url %}
<br/><br/>
{% blocktrans %}Your account details are as follows:<br/><br/>
Username : Your email address<br/>
Password : {{account_details}}<br/><br/>
You can reset your password here:
{{base_url}}{{reset_password_url}}
{% endblocktrans %}
{% endif %}
{% endblock %} {% endblock %}

View file

@ -7,4 +7,15 @@ You can also copy and paste the following link into the address bar of your brow
to activate your Data Center Light account. to activate your Data Center Light account.
{{base_url}}{{activation_link}} {{base_url}}{{activation_link}}
{% endblocktrans %} {% endblocktrans %}
{% if account_details %}
{% url 'hosting:reset_password' as reset_password_url %}
{% blocktrans %}Your account details are as follows:
Username : Your email address
Password : {{account_details}}
You can reset your password here:
{{base_url}}{{reset_password_url}}
{% endblocktrans %}
{% endif %}
{% endblock %} {% endblock %}

View file

@ -1,190 +1,182 @@
{% extends "hosting/base_short.html" %} {% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %} {% load staticfiles bootstrap3 i18n %}
{% block css_extra %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
{% endblock css_extra %}
{% block navbar %} {% block navbar %}
{% include "datacenterlight/includes/_navbar.html" %} {% include "datacenterlight/includes/_navbar.html" %}
{% endblock navbar %} {% endblock navbar %}
{% block content %} {% block content %}
<!-- Credit card form --> <!-- Credit card form -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
<div class="dcl-order-container"> <div class="dcl-order-container">
<div class="payment-container"> <div class="payment-container">
<div class="row"> <div class="dcl-payment-grid">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-order-sec"> <div class="dcl-payment-box">
<h3><strong>{%trans "Your Order" %}</strong></h3> <div class="dcl-payment-section">
<div class="col-xs-6 col-sm-12 col-md-12 col-lg-12 dcl-order-table-header"> {% if request.user.is_authenticated %}
<div class="col-xs-12 col-sm-2 col-md-1 col-lg-1 tbl-header"> <div class="dcl-payment-user">
{%trans "Cores" %} <h4>{% trans "Welcome back" %} {{request.user.name}}!</h4>
</div> <p>{% trans "Review your billing address and card details and proceed to make payment." %}</p>
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4 tbl-header">
{%trans "Memory" %}
</div>
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 tbl-header">
{%trans "Disk space" %}
</div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-header">
{%trans "Configuration" %}
</div>
</div>
<div class="col-xs-6 col-sm-12 col-md-12 col-lg-12 dcl-order-table-content">
<div class="col-xs-12 col-sm-2 col-md-1 col-lg-1 tbl-content">
{{request.session.specs.cpu|floatformat}}
</div>
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4 tbl-content">
{{request.session.specs.memory|floatformat}} GB
</div>
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 tbl-content">
{{request.session.specs.disk_size|floatformat}} GB
</div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-content">
{{request.session.template.name}}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-order-table-total">
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 tbl-tot tbl-no-padding">
{%trans "Total" %} <span>{%trans "including VAT" %}</span>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 tbl-no-padding">
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4"></div>
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 tbl-total">{{request.session.specs.price}}
CHF<span class="dcl-price-month">/{% trans "Month" %}</span>
</div> </div>
</div> {% else %}
<h3>{%trans "Log in" %}</h3>
<hr class="top-hr">
<p style="margin-bottom: 20px;">{% blocktrans %}Already signed up?<br>By logging in you can retrieve saved billing information.{% endblocktrans %}</p>
<form role="form" id="login-form" method="post" action="{% url 'hosting:login' %}" novalidate>
{% for field in login_form %}
{% csrf_token %}
{% bootstrap_field field show_label=False type='fields'%}
{% endfor %}
<input type='hidden' name='next' value='{{request.path}}'/>
<div class="form-group text-right">
<button type="submit" class="btn btn-wide btn-vm-contact">{% trans "LOGIN" %}</button>
</div>
</form>
<p>
{% trans "Don't have an account yet?" %}<br>
{% trans "You can sign up by filling in the information below." %}<br>
<a href="{% url 'hosting:reset_password' %}">{% trans "Forgot password?" %}</a>
</p>
{% endif %}
</div> </div>
</div> </div>
</div> <div class="dcl-payment-box">
<div class="row"> <div class="dcl-payment-section">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-billing-sec"> {% if not request.user.is_authenticated %}
<div class="col-xs-12 col-sm-5 col-md-6 billing dcl-billing"> <h3><b>{%trans "Sign up"%}</b></h3>
<h3><b>{%trans "Billing Address"%}</b></h3> {% else %}
<hr> <h3><b>{%trans "Billing Address"%}</b></h3>
{% endif %}
<hr class="top-hr">
{% for message in messages %}
{% if 'duplicate_email' in message.tags %}
<p class="text-danger">{{message}}</p>
{% endif %}
{% endfor %}
<form role="form" id="billing-form" method="post" action="" novalidate> <form role="form" id="billing-form" method="post" action="" novalidate>
{% for field in form %}
{% csrf_token %} {% csrf_token %}
{% for field in form %}
{% bootstrap_field field show_label=False type='fields'%} {% bootstrap_field field show_label=False type='fields'%}
{% endfor %} {% endfor %}
</form> </form>
</div> </div>
<div class="col-xs-12 col-sm-7 col-md-6 creditcard-box dcl-creditcard"> </div>
<div class="dcl-payment-box">
<div class="dcl-payment-section">
<h3>{%trans "Your Order" %}</h3>
<hr class="top-hr">
<div class="dcl-payment-order">
<p>{% trans "Cores"%} <strong class="pull-right">{{request.session.specs.cpu|floatformat}}</strong></p>
<hr>
<p>{% trans "Memory"%} <strong class="pull-right">{{request.session.specs.memory|floatformat}} GB</strong></p>
<hr>
<p>{% trans "Disk space"%} <strong class="pull-right">{{request.session.specs.disk_size|floatformat}} GB</strong></p>
<hr>
<p>{% trans "Configuration"%} <strong class="pull-right">{{request.session.template.name}}</strong></p>
<hr>
<p class="last-p"><strong>{%trans "Total" %}</strong>&nbsp;&nbsp;<small>({%trans "including VAT" %})</small> <strong class="pull-right">{{request.session.specs.price}} CHF/{% trans "Month" %}</strong></p>
</div>
</div>
</div>
<div class="dcl-payment-box">
<div class="dcl-payment-section">
<h3><b>{%trans "Credit Card"%}</b></h3> <h3><b>{%trans "Credit Card"%}</b></h3>
<hr> <hr class="top-hr">
<p>
{% blocktrans %}Please fill in your credit card information below. We are using <a href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store your information in our database.{% endblocktrans %}
</p>
<div> <div>
<div> {% if credit_card_data.last4 %}
<p>
{% blocktrans %}
Please fill in your credit card information below. We are using <a
href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store
your information in our database.
{% endblocktrans %}
</p>
</div>
<br>
<div>
{% if credit_card_data.last4 %}
<form role="form" id="payment-form-with-creditcard" novalidate> <form role="form" id="payment-form-with-creditcard" novalidate>
<h5 class="billing-head">Credit Card</h5> <h5 class="billing-head">Credit Card</h5>
<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="row"> {% if not messages and not form.non_field_errors %}
<div class="col-xs-12"> <p class="card-warning-content card-warning-addtional-margin">
{% if not messages and not form.non_field_errors %} {% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
<p class="card-warning-content card-warning-addtional-margin"> </p>
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %} {% endif %}
</p> <div id='payment_error'>
{% endif %} {% for message in messages %}
<div id='payment_error'> {% if 'failed_payment' or 'make_charge_error' in message.tags %}
{% for message in messages %} <ul class="list-unstyled"><li>
{% if 'failed_payment' or 'make_charge_error' in message.tags %} <p class="card-warning-content card-warning-error">{{ message|safe }}</p>
<ul class="list-unstyled"><li> </li></ul>
<p class="card-warning-content card-warning-error">{{ message|safe }}</p> {% endif %}
</li></ul> {% endfor %}
{% endif %} {% for error in form.non_field_errors %}
{% endfor %} <p class="card-warning-content card-warning-error">
{% for error in form.non_field_errors %} {{ error|escape }}
<p class="card-warning-content card-warning-error"> </p>
{{ error|escape }} {% endfor %}
</p>
{% endfor %}
</div>
</div>
<div class="col-xs-12">
<div class="col-xs-6 pull-right">
<button id="payment_button_with_creditcard" class="btn btn-success stripe-payment-btn"
type="submit">
{%trans "Submit" %}
</button>
</div>
</div>
</div> </div>
<div class="text-right">
{% else %} <button id="payment_button_with_creditcard" class="btn btn-success btn-vm-contact" type="submit">{%trans "Submit" %}</button>
</div>
{% else %}
<form action="" id="payment-form-new" method="POST"> <form action="" id="payment-form-new" method="POST">
<input type="hidden" name="token"/> <input type="hidden" name="token"/>
<div class="group"> <div class="group">
<div class="col-xs-12 col-sm-12 col-md-10 col-lg-9 credit-card-goup"> <div class="credit-card-goup">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 card-element card-number-element"> <div class="card-element card-number-element">
<label>{%trans "Card Number" %}</label> <label>{%trans "Card Number" %}</label>
<div id="card-number-element" class="field my-input"></div> <div id="card-number-element" class="field my-input"></div>
</div> </div>
<div class="col-xs-5 col-sm-3 col-md-3 col-lg-3 card-element card-expiry-element"> <div class="row">
<label>{%trans "Expiry Date" %}</label> <div class="col-xs-5 card-element card-expiry-element">
<div id="card-expiry-element" class="field my-input"></div> <label>{%trans "Expiry Date" %}</label>
<div id="card-expiry-element" class="field my-input"></div>
</div>
<div class="col-xs-3 col-xs-offset-4 card-element card-cvc-element">
<label>{%trans "CVC" %}</label>
<div id="card-cvc-element" class="field my-input"></div>
</div>
</div> </div>
<div class="col-xs-12 col-sm-2 col-md-6 col-lg-7 hide-mobile"></div> <div class="card-element brand">
<div class="col-xs-3 col-sm-3 col-md-3 col-lg-2 card-element card-cvc-element">
<label>{%trans "CVC" %}</label>
<div id="card-cvc-element" class="field my-input"></div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 card-element brand">
<label>{%trans "Card Type" %}</label> <label>{%trans "Card Type" %}</label>
<i class="pf pf-credit-card" id="brand-icon"></i> <i class="pf pf-credit-card" id="brand-icon"></i>
</div> </div>
</div> </div>
</div> </div>
<div id="card-errors" role="alert"></div> <div id="card-errors"></div>
<div class="row"> {% if not messages and not form.non_field_errors %}
<div class="col-xs-12"> <p class="card-warning-content">
{% if not messages and not form.non_field_errors %} {% trans "You are not making any payment yet. After placing your order, you will be taken to the Submit Payment Page." %}
</p>
{% endif %}
<div id='payment_error'>
{% for message in messages %}
{% if 'failed_payment' in message.tags 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>
{% elif not form.non_field_errors %}
<p class="card-warning-content"> <p class="card-warning-content">
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %} {% trans "You are not making any payment yet. After placing your order, you will be taken to the Submit Payment Page." %}
</p> </p>
{% endif %} {% endif %}
<div id='payment_error'> {% endfor %}
{% 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 %} {% for error in form.non_field_errors %}
<p class="card-warning-content card-warning-error"> <p class="card-warning-content card-warning-error">
{{ error|escape }} {{ error|escape }}
</p> </p>
{% endfor %} {% endfor %}
</div> </div>
</div> <div class="text-right">
<div class="col-xs-12"> <button class="btn btn-vm-contact btn-wide" type="submit">{%trans "SUBMIT" %}</button>
<div class="col-xs-6 pull-right">
<button class="btn btn-success stripe-payment-btn" type="submit">{%trans "Submit" %}
</button>
</div>
</div>
</div> </div>
<div class="row" style="display:none;"> <div style="display:none;">
<div class="col-xs-12"> <p class="payment-errors"></p>
<p class="payment-errors"></p>
</div>
</div> </div>
</form> </form>
{% endif %}
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -17,4 +17,5 @@
</div> </div>
</div> </div>
</form> </form>
{% endblock submit_btn %} {% endblock submit_btn %}

View file

@ -1,19 +1,26 @@
import logging
import json
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import login, authenticate
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import get_language, ugettext_lazy as _
from django.views.decorators.cache import cache_control from django.views.decorators.cache import cache_control
from django.views.generic import FormView, CreateView, TemplateView, DetailView from django.views.generic import FormView, CreateView, TemplateView, DetailView
from datacenterlight.tasks import create_vm_task from datacenterlight.tasks import create_vm_task
from hosting.models import HostingOrder from hosting.models import HostingOrder
from hosting.forms import HostingUserLoginForm
from membership.models import CustomUser, StripeCustomer from membership.models import CustomUser, StripeCustomer
from opennebula_api.serializers import VMTemplateSerializer from opennebula_api.serializers import VMTemplateSerializer
from utils.forms import BillingAddressForm from utils.forms import (
BillingAddressForm, BillingAddressFormSignup, UserBillingAddressForm
)
from utils.hosting_utils import get_vm_price from utils.hosting_utils import get_vm_price
from utils.mailer import BaseEmail from utils.mailer import BaseEmail
from utils.stripe_utils import StripeUtils from utils.stripe_utils import StripeUtils
@ -21,6 +28,8 @@ from utils.tasks import send_plain_email_task
from .forms import BetaAccessForm, ContactForm from .forms import BetaAccessForm, ContactForm
from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate
logger = logging.getLogger(__name__)
class ContactUsView(FormView): class ContactUsView(FormView):
template_name = "datacenterlight/contact_form.html" template_name = "datacenterlight/contact_form.html"
@ -227,11 +236,6 @@ class IndexView(CreateView):
opennebula_vm_template_id=template_id).first() opennebula_vm_template_id=template_id).first()
template_data = VMTemplateSerializer(template).data template_data = VMTemplateSerializer(template).data
name = request.POST.get('name')
email = request.POST.get('email')
name_field = forms.CharField()
email_field = forms.EmailField()
try: try:
cores = cores_field.clean(cores) cores = cores_field.clean(cores)
except ValidationError as err: except ValidationError as err:
@ -258,39 +262,16 @@ class IndexView(CreateView):
extra_tags='storage') extra_tags='storage')
return HttpResponseRedirect( return HttpResponseRedirect(
reverse('datacenterlight:index') + "#order_form") reverse('datacenterlight:index') + "#order_form")
amount_to_be_charged = get_vm_price(cpu=cores, memory=memory,
try: disk_size=storage)
name = name_field.clean(name)
except ValidationError as err:
msg = '{} {}.'.format(name, _('is not a proper name'))
messages.add_message(self.request, messages.ERROR, msg,
extra_tags='name')
return HttpResponseRedirect(
reverse('datacenterlight:index') + "#order_form")
try:
email = email_field.clean(email)
except ValidationError as err:
msg = '{} {}.'.format(email, _('is not a proper email'))
messages.add_message(self.request, messages.ERROR, msg,
extra_tags='email')
return HttpResponseRedirect(
reverse('datacenterlight:index') + "#order_form")
specs = { specs = {
'cpu': cores, 'cpu': cores,
'memory': memory, 'memory': memory,
'disk_size': storage, 'disk_size': storage,
'price': amount_to_be_charged
} }
this_user = {
'name': name,
'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
return HttpResponseRedirect(reverse('datacenterlight:payment')) return HttpResponseRedirect(reverse('datacenterlight:payment'))
def get_success_url(self): def get_success_url(self):
@ -353,20 +334,19 @@ class WhyDataCenterLightView(IndexView):
class PaymentOrderView(FormView): class PaymentOrderView(FormView):
template_name = 'datacenterlight/landing_payment.html' template_name = 'datacenterlight/landing_payment.html'
form_class = BillingAddressForm
def get_form_class(self):
if self.request.user.is_authenticated():
return BillingAddressForm
else:
return BillingAddressFormSignup
def get_form_kwargs(self): def get_form_kwargs(self):
form_kwargs = super(PaymentOrderView, self).get_form_kwargs() form_kwargs = super(PaymentOrderView, self).get_form_kwargs()
billing_address_data = self.request.session.get('billing_address_data') # if user is signed in, get billing address
if billing_address_data: if self.request.user.is_authenticated():
form_kwargs.update({ form_kwargs.update({
'initial': { 'instance': self.request.user.billing_addresses.first()
'cardholder_name': billing_address_data['cardholder_name'],
'street_address': billing_address_data['street_address'],
'city': billing_address_data['city'],
'postal_code': billing_address_data['postal_code'],
'country': billing_address_data['country'],
}
}) })
return form_kwargs return form_kwargs
@ -374,48 +354,49 @@ class PaymentOrderView(FormView):
context = super(PaymentOrderView, self).get_context_data(**kwargs) context = super(PaymentOrderView, self).get_context_data(**kwargs)
context.update({ context.update({
'stripe_key': settings.STRIPE_API_PUBLIC_KEY, 'stripe_key': settings.STRIPE_API_PUBLIC_KEY,
'site_url': reverse('datacenterlight:index') 'site_url': reverse('datacenterlight:index'),
'login_form': HostingUserLoginForm()
}) })
return context return context
@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' not in request.session or 'user' not in request.session: # user is no longer added to session on the index page
if 'specs' not in request.session:
return HttpResponseRedirect(reverse('datacenterlight:index')) return HttpResponseRedirect(reverse('datacenterlight:index'))
return self.render_to_response(self.get_context_data()) return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.get_form() form = self.get_form()
if form.is_valid(): if form.is_valid():
# Get billing address data
billing_address_data = form.cleaned_data
token = form.cleaned_data.get('token') token = form.cleaned_data.get('token')
user = request.session.get('user') if request.user.is_authenticated():
try: this_user = {
CustomUser.objects.get(email=user.get('email')) 'email': request.user.email,
except CustomUser.DoesNotExist: 'name': request.user.name
password = CustomUser.get_random_password() }
# Register the user, and do not send emails customer = StripeCustomer.get_or_create(
CustomUser.register(user.get('name'), email=this_user.get('email'),
password, token=token)
user.get('email'), else:
app='dcl', this_user = {
base_url=None, send_email=False) 'email': form.cleaned_data.get('email'),
'name': form.cleaned_data.get('name')
}
customer = StripeCustomer.create_stripe_api_customer(
email=this_user.get('email'),
token=token,
customer_name=form.cleaned_data.get('name'))
request.session['billing_address_data'] = form.cleaned_data
request.session['user'] = this_user
# Get or create stripe customer # Get or create stripe customer
customer = StripeCustomer.get_or_create(email=user.get('email'),
token=token)
if not customer: if not customer:
form.add_error("__all__", "Invalid credit card") form.add_error("__all__", "Invalid credit card")
return self.render_to_response( return self.render_to_response(
self.get_context_data(form=form)) self.get_context_data(form=form))
# Create Billing Address
billing_address = form.save()
request.session['billing_address_data'] = billing_address_data
request.session['billing_address'] = billing_address.id
request.session['token'] = token request.session['token'] = token
request.session['customer'] = customer.id request.session[
'customer'] = customer.id if request.user.is_authenticated() else customer
return HttpResponseRedirect( return HttpResponseRedirect(
reverse('datacenterlight:order_confirmation')) reverse('datacenterlight:order_confirmation'))
else: else:
@ -435,9 +416,15 @@ class OrderConfirmationView(DetailView):
if 'token' not in request.session: if 'token' not in request.session:
return HttpResponseRedirect(reverse('datacenterlight:payment')) return HttpResponseRedirect(reverse('datacenterlight:payment'))
stripe_customer_id = request.session.get('customer') stripe_customer_id = request.session.get('customer')
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() if request.user.is_authenticated():
customer = StripeCustomer.objects.filter(
id=stripe_customer_id).first()
stripe_api_cus_id = customer.stripe_id
else:
stripe_api_cus_id = stripe_customer_id
stripe_utils = StripeUtils() stripe_utils = StripeUtils()
card_details = stripe_utils.get_card_details(customer.stripe_id, card_details = stripe_utils.get_card_details(stripe_api_cus_id,
request.session.get( request.session.get(
'token')) 'token'))
if not card_details.get('response_object'): if not card_details.get('response_object'):
@ -452,6 +439,7 @@ class OrderConfirmationView(DetailView):
'cc_brand': card_details.get('response_object').get('brand'), 'cc_brand': card_details.get('response_object').get('brand'),
'vm': request.session.get('specs'), 'vm': request.session.get('specs'),
'page_header_text': _('Confirm Order') 'page_header_text': _('Confirm Order')
'billing_address_data': request.session.get('billing_address_data')
} }
return render(request, self.template_name, context) return render(request, self.template_name, context)
@ -460,29 +448,40 @@ class OrderConfirmationView(DetailView):
specs = request.session.get('specs') specs = request.session.get('specs')
user = request.session.get('user') user = request.session.get('user')
stripe_customer_id = request.session.get('customer') stripe_customer_id = request.session.get('customer')
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() if request.user.is_authenticated():
billing_address_data = request.session.get('billing_address_data') customer = StripeCustomer.objects.filter(
billing_address_id = request.session.get('billing_address') id=stripe_customer_id).first()
stripe_api_cus_id = customer.stripe_id
else:
stripe_api_cus_id = stripe_customer_id
vm_template_id = template.get('id', 1) vm_template_id = template.get('id', 1)
# Make stripe charge to a customer
stripe_utils = StripeUtils() stripe_utils = StripeUtils()
card_details = stripe_utils.get_card_details(customer.stripe_id, card_details = stripe_utils.get_card_details(stripe_api_cus_id,
request.session.get( request.session.get(
'token')) 'token'))
if not card_details.get('response_object'): if not card_details.get('response_object'):
msg = card_details.get('error') msg = card_details.get('error')
messages.add_message(self.request, messages.ERROR, msg, messages.add_message(self.request, messages.ERROR, msg,
extra_tags='failed_payment') extra_tags='failed_payment')
return HttpResponseRedirect( response = {
reverse('datacenterlight:payment') + '#payment_error') 'status': False,
'redirect': "{url}#{section}".format(
url=reverse('datacenterlight:payment'),
section='payment_error'),
'msg_title': str(_('Error.')),
'msg_body': str(
_('There was a payment related error.'
' On close of this popup, you will be redirected back to'
' the payment page.'))
}
return HttpResponse(json.dumps(response),
content_type="application/json")
card_details_dict = card_details.get('response_object') card_details_dict = card_details.get('response_object')
cpu = specs.get('cpu') cpu = specs.get('cpu')
memory = specs.get('memory') memory = specs.get('memory')
disk_size = specs.get('disk_size') disk_size = specs.get('disk_size')
amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory, amount_to_be_charged = specs.get('price')
disk_size=disk_size)
specs['price'] = amount_to_be_charged
plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu, plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu,
memory=memory, memory=memory,
disk_size=disk_size) disk_size=disk_size)
@ -496,7 +495,7 @@ class OrderConfirmationView(DetailView):
name=plan_name, name=plan_name,
stripe_plan_id=stripe_plan_id) stripe_plan_id=stripe_plan_id)
subscription_result = stripe_utils.subscribe_customer_to_plan( subscription_result = stripe_utils.subscribe_customer_to_plan(
customer.stripe_id, stripe_api_cus_id,
[{"plan": stripe_plan.get( [{"plan": stripe_plan.get(
'response_object').stripe_plan_id}]) 'response_object').stripe_plan_id}])
stripe_subscription_obj = subscription_result.get('response_object') stripe_subscription_obj = subscription_result.get('response_object')
@ -506,11 +505,96 @@ class OrderConfirmationView(DetailView):
msg = subscription_result.get('error') msg = subscription_result.get('error')
messages.add_message(self.request, messages.ERROR, msg, messages.add_message(self.request, messages.ERROR, msg,
extra_tags='failed_payment') extra_tags='failed_payment')
return HttpResponseRedirect( response = {
reverse('datacenterlight:payment') + '#payment_error') 'status': False,
'redirect': "{url}#{section}".format(
url=reverse('datacenterlight:payment'),
section='payment_error'),
'msg_title': str(_('Error.')),
'msg_body': str(
_('There was a payment related error.'
' On close of this popup, you will be redirected back to'
' the payment page.'))
}
return HttpResponse(json.dumps(response),
content_type="application/json")
# Create user if the user is not logged in and if he is not already
# registered
if not request.user.is_authenticated():
try:
custom_user = CustomUser.objects.get(
email=user.get('email'))
customer = StripeCustomer.objects.filter(
user_id=custom_user.id).first()
stripe_customer_id = customer.id
except CustomUser.DoesNotExist:
logger.debug(
"Customer {} does not exist.".format(user.get('email')))
password = CustomUser.get_random_password()
base_url = "{0}://{1}".format(self.request.scheme,
self.request.get_host())
custom_user = CustomUser.register(
user.get('name'), password,
user.get('email'),
app='dcl', base_url=base_url, send_email=True,
account_details=password
)
logger.debug("Created user {}.".format(user.get('email')))
stripe_customer = StripeCustomer.objects. \
create(user=custom_user, stripe_id=stripe_api_cus_id)
stripe_customer_id = stripe_customer.id
new_user = authenticate(username=custom_user.email,
password=password)
login(request, new_user)
else:
customer = StripeCustomer.objects.filter(
id=stripe_customer_id).first()
custom_user = customer.user
stripe_customer_id = customer.id
# Save billing address
billing_address_data = request.session.get('billing_address_data')
logger.debug('billing_address_data is {}'.format(billing_address_data))
billing_address_data.update({
'user': custom_user.id
})
billing_address_user_form = UserBillingAddressForm(
instance=custom_user.billing_addresses.first(),
data=billing_address_data)
billing_address = billing_address_user_form.save()
billing_address_id = billing_address.id
logger.debug("billing address id = {}".format(billing_address_id))
user = {
'name': custom_user.name,
'email': custom_user.email,
'pass': custom_user.password,
'request_scheme': request.scheme,
'request_host': request.get_host(),
'language': get_language(),
}
create_vm_task.delay(vm_template_id, user, specs, template, create_vm_task.delay(vm_template_id, user, specs, template,
stripe_customer_id, billing_address_data, stripe_customer_id, billing_address_data,
billing_address_id, billing_address_id,
stripe_subscription_obj, card_details_dict) stripe_subscription_obj, card_details_dict)
request.session['order_confirmation'] = True for session_var in ['specs', 'template', 'billing_address',
return HttpResponseRedirect(reverse('datacenterlight:order_success')) 'billing_address_data',
'token', 'customer']:
if session_var in request.session:
del request.session[session_var]
response = {
'status': True,
'redirect': reverse(
'hosting:virtual_machines') if request.user.is_authenticated() else reverse(
'datacenterlight:index'),
'msg_title': str(_('Thank you for the order.')),
'msg_body': str(
_('Your VM will be up and running in a few moments.'
' We will send you a confirmation email as soon as'
' it is ready.'))
}
return HttpResponse(json.dumps(response),
content_type="application/json")

View file

@ -268,7 +268,7 @@ msgstr ""
"Link klickst</a>.<br/>\n" "Link klickst</a>.<br/>\n"
msgid "My VM page" msgid "My VM page"
msgstr "" msgstr "Meine VM page"
#, python-format #, python-format
msgid "" msgid ""
@ -629,7 +629,7 @@ msgid "View Detail"
msgstr "Details anzeigen" msgstr "Details anzeigen"
msgid "login" msgid "login"
msgstr "Einloggen" msgstr "anmelden"
msgid "" msgid ""
"Thank you for signing up. We have sent an email to you. Please follow the " "Thank you for signing up. We have sent an email to you. Please follow the "

View file

@ -857,6 +857,8 @@ a.list-group-item-danger:focus,
background: rgba(235, 204, 209, 0.2); background: rgba(235, 204, 209, 0.2);
} }
.has-error .form-control, .has-error .form-control,
.has-error .form-control:focus,
.has-error .form-control:active,
.has-error .input-group-addon { .has-error .input-group-addon {
color: #eb4d5c; color: #eb4d5c;
border-color: #eb4d5c; border-color: #eb4d5c;
@ -871,6 +873,13 @@ a.list-group-item-danger.active:focus {
background-color: #eb4d5c; background-color: #eb4d5c;
} }
/* bootstrap input box-shadom disable */
.has-error .form-control:focus,
.has-error .form-control:active,
.has-success .form-control:focus,
.has-success .form-control:active {
box-shadow: inset 0 0 1px rgba(0,0,0,0.25);
}
.checkmark { .checkmark {
display: inline-block; display: inline-block;
} }

View file

@ -22,7 +22,100 @@
} }
.summary-box .content { .summary-box .content {
padding-top: 15px; padding-top: 15px;
}
/* landing page payment new style */
.last-p {
margin-bottom: 0;
}
.dcl-payment-section {
max-width: 391px;
margin: 0 auto 30px;
padding: 0 10px 30px;
border-bottom: 1px solid #edebeb;
height: 100%;
}
.dcl-payment-section hr{
margin-top: 15px;
margin-bottom: 15px;
}
.dcl-payment-section .top-hr {
margin-left: -10px;
}
.dcl-payment-section h3 {
font-weight: 600;
}
.dcl-payment-section p {
padding: 0 5px;
font-weight: 400;
}
.dcl-payment-section .card-warning-content {
padding: 8px 10px;
font-weight: 300;
}
.dcl-payment-order strong{
font-size: 17px;
}
.dcl-payment-order p {
font-weight: 300;
}
.dcl-payment-section .form-group {
margin-bottom: 10px;
}
.dcl-payment-section .form-control {
box-shadow: none;
padding: 6px 12px;
height: 32px;
}
.dcl-payment-user {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.dcl-payment-user h4 {
font-weight: 600;
padding-left: 5px;
font-size: 17px;
}
@media (min-width: 768px) {
.dcl-payment-grid {
display: flex;
align-items: stretch;
flex-wrap: wrap;
}
.dcl-payment-box {
width: 50%;
position: relative;
padding: 0 30px;
}
.dcl-payment-box:nth-child(2) {
order: 1;
}
.dcl-payment-box:nth-child(4) {
order: 2;
}
.dcl-payment-section {
padding: 15px 10px;
margin-bottom: 0;
border-bottom-width: 5px;
}
.dcl-payment-box:nth-child(2n) .dcl-payment-section {
border-bottom: none;
}
.dcl-payment-box:nth-child(1):after,
.dcl-payment-box:nth-child(2):after {
content: ' ';
display: block;
background: #eee;
width: 1px;
position: absolute;
right: 0;
z-index: 2;
top: 20px;
bottom: 20px;
}
} }

View file

@ -13,7 +13,12 @@
{% endif %} {% endif %}
{% if not error %} {% if not error %}
<div class="dashboard-subtitle"> <div class="dashboard-subtitle">
<p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p> <p>{% trans 'To create a new virtual machine, click "Create VM"' %}
{% if show_create_ssh_key_msg %}
{% url 'hosting:create_ssh_key' as create_ssh_url %}
<br/>{% blocktrans %}To access your VM, add your SSH key <a href="{{create_ssh_url}}">here</a>{% endblocktrans %}
{% endif %}
</p>
<div class="text-right"> <div class="text-right">
<a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM" %}</span></a> <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM" %}</span></a>
</div> </div>

View file

@ -613,13 +613,6 @@ 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():
messages.success(
request,
'In order to create a VM, you create/upload your SSH KEY first.'
)
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
if 'next' in request.session: if 'next' in request.session:
del request.session['next'] del request.session['next']
@ -885,6 +878,10 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
context = {'error': 'connection'} context = {'error': 'connection'}
else: else:
context = super(ListView, self).get_context_data(**kwargs) context = super(ListView, self).get_context_data(**kwargs)
if UserHostingKey.objects.filter(user=self.request.user).exists():
context['show_create_ssh_key_msg'] = False
else:
context['show_create_ssh_key_msg'] = True
return context return context
@ -905,15 +902,6 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
raise ValidationError(_('Invalid storage size')) raise ValidationError(_('Invalid storage size'))
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if not UserHostingKey.objects.filter(user=self.request.user).exists():
messages.success(
request,
_(
'In order to create a VM, you need to '
'create/upload your SSH KEY first.'
)
)
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
context = {'templates': VMTemplate.objects.all()} context = {'templates': VMTemplate.objects.all()}
return render(request, self.template_name, context) return render(request, self.template_name, context)

View file

@ -82,7 +82,7 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
@classmethod @classmethod
def register(cls, name, password, email, app='digital_glarus', def register(cls, name, password, email, app='digital_glarus',
base_url=None, send_email=True): base_url=None, send_email=True, account_details=None):
user = cls.objects.filter(email=email).first() user = cls.objects.filter(email=email).first()
if not user: if not user:
user = cls.objects.create_user(name=name, email=email, user = cls.objects.create_user(name=name, email=email,
@ -112,6 +112,9 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
'template_name': 'user_activation', 'template_name': 'user_activation',
'template_path': 'datacenterlight/emails/' 'template_path': 'datacenterlight/emails/'
} }
if account_details:
email_data['context'][
'account_details'] = account_details
email = BaseEmail(**email_data) email = BaseEmail(**email_data)
email.send() email.send()
return user return user
@ -176,6 +179,25 @@ class StripeCustomer(models.Model):
def __str__(self): def __str__(self):
return "%s - %s" % (self.stripe_id, self.user.email) return "%s - %s" % (self.stripe_id, self.user.email)
@classmethod
def create_stripe_api_customer(cls, email=None, token=None,
customer_name=None):
"""
This method creates a Stripe API customer with the given
email, token and customer_name. This is different from
get_or_create method below in that it does not create a
CustomUser and associate the customer created in stripe
with it, while get_or_create does that before creating the
stripe user.
"""
stripe_utils = StripeUtils()
stripe_data = stripe_utils.create_customer(token, email, customer_name)
if stripe_data.get('response_object'):
stripe_cus_id = stripe_data.get('response_object').get('id')
return stripe_cus_id
else:
return None
@classmethod @classmethod
def get_or_create(cls, email=None, token=None): def get_or_create(cls, email=None, token=None):
""" """
@ -195,7 +217,6 @@ class StripeCustomer(models.Model):
except StripeCustomer.DoesNotExist: except StripeCustomer.DoesNotExist:
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, user.name) stripe_data = stripe_utils.create_customer(token, email, user.name)
if stripe_data.get('response_object'): if stripe_data.get('response_object'):

View file

@ -150,9 +150,10 @@ class OpenNebulaManager():
oca.User.METHODS['allocate'], email, oca.User.METHODS['allocate'], email,
password, 'core') password, 'core')
logger.debug( logger.debug(
"User {0} does not exist. Created the user. User id = {1}", "User {} does not exist. Created the user. User id = {}".format(
email, email,
opennebula_user opennebula_user
)
) )
return opennebula_user return opennebula_user
except ConnectionRefusedError: except ConnectionRefusedError:

View file

@ -131,6 +131,12 @@ class BillingAddressForm(forms.ModelForm):
} }
class BillingAddressFormSignup(BillingAddressForm):
name = forms.CharField(label=_('Name'))
email = forms.EmailField(label=_('Email Address'))
field_order = ['name', 'email']
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())