Merge pull request #88 from levivm/develop

Develop
This commit is contained in:
Levi Velázquez 2016-06-21 00:17:55 -05:00 committed by GitHub
commit 05b8493fe1
24 changed files with 263 additions and 32 deletions

View File

@ -8,6 +8,8 @@ ADMINS = (
) )
# ('Sanghee Kim', 'sanghee.kim@ungleich.ch'), # ('Sanghee Kim', 'sanghee.kim@ungleich.ch'),
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
#MANAGERS = ADMINS #MANAGERS = ADMINS
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='digitalglarus.ungleich.ch',slug='{slug}') REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='digitalglarus.ungleich.ch',slug='{slug}')

View File

@ -25,7 +25,7 @@ urlpatterns += i18n_patterns('',
url(r'^digitalglarus/login/', include(membership_urls)), url(r'^digitalglarus/login/', include(membership_urls)),
url(r'^digitalglarus/', include('digitalglarus.urls', url(r'^digitalglarus/', include('digitalglarus.urls',
namespace="digitalglarus")), namespace="digitalglarus")),
url(r'^blog/', include('ungleich.urls', namespace='ungleich')), # url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
url(r'^ungleich_page/', url(r'^ungleich_page/',
include('ungleich_page.urls', namespace='ungleich_page'), include('ungleich_page.urls', namespace='ungleich_page'),
name='ungleich_page'), name='ungleich_page'),

View File

@ -32,10 +32,11 @@ class HostingOrderAdmin(admin.ModelAdmin):
context = { context = {
'order': obj, 'order': obj,
'vm': obj.vm_plan 'vm': obj.vm_plan,
'base_url': "{0}://{1}".format(request.scheme, request.get_host())
} }
email_data = { email_data = {
'subject': 'New VM request', 'subject': 'Your VM plan has been charged',
'to': obj.customer.user.email, 'to': obj.customer.user.email,
'context': context, 'context': context,
'template_name': 'vm_charged', 'template_name': 'vm_charged',
@ -75,7 +76,8 @@ class VirtualMachinePlanAdmin(admin.ModelAdmin):
email = self.email(obj) email = self.email(obj)
if 'status' in form.changed_data: if 'status' in form.changed_data:
context = { context = {
'vm': obj 'vm': obj,
'base_url': "{0}://{1}".format(request.scheme, request.get_host())
} }
email_data = { email_data = {
'subject': 'Your VM has been activated', 'subject': 'Your VM has been activated',

View File

@ -4,7 +4,7 @@ from django.contrib.auth import authenticate
from utils.stripe_utils import StripeUtils from utils.stripe_utils import StripeUtils
from .models import HostingOrder from .models import HostingOrder, VirtualMachinePlan
class HostingOrderAdminForm(forms.ModelForm): class HostingOrderAdminForm(forms.ModelForm):
@ -17,6 +17,10 @@ class HostingOrderAdminForm(forms.ModelForm):
customer = self.cleaned_data.get('customer') customer = self.cleaned_data.get('customer')
vm_plan = self.cleaned_data.get('vm_plan') vm_plan = self.cleaned_data.get('vm_plan')
if vm_plan.status == VirtualMachinePlan.CANCELED_STATUS:
raise forms.ValidationError("""You can't make a charge over
a canceled virtual machine plan""")
# Make a charge to the customer # Make a charge to the customer
stripe_utils = StripeUtils() stripe_utils = StripeUtils()
charge_response = stripe_utils.make_charge(customer=customer.stripe_id, charge_response = stripe_utils.make_charge(customer=customer.stripe_id,
@ -53,7 +57,7 @@ class HostingUserLoginForm(forms.Form):
CustomUser.objects.get(email=email) CustomUser.objects.get(email=email)
return email return email
except CustomUser.DoesNotExist: except CustomUser.DoesNotExist:
raise forms.ValidationError("User does not exists") raise forms.ValidationError("User does not exist")
else: else:
return email return email

View File

@ -83,6 +83,12 @@ h6 {
height: 100%; height: 100%;
} }
.intro-reset-password {
background: url(../img/signup-bg.png) no-repeat center center;
background-size: cover;
height: 100%;
}
.intro-message > h1 { .intro-message > h1 {
margin: 0; margin: 0;
font-weight: 400; font-weight: 400;

View File

@ -114,7 +114,7 @@
<w:anchorlock/> <w:anchorlock/>
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center> <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
</v:roundrect> </v:roundrect>
<![endif]--><a href="{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a> <![endif]--><a href="{{ base_url }}{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -101,7 +101,7 @@
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center"> <td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
Your virtual machine {{vm.name}} subscription has been charged, Your virtual machine {{vm.name}} subscription has been charged,
<br/> <br/>
We are going to contact you as soon your virtual machine has been activated. we are going to contact you as soon your virtual machine has been activated.
<br/> <br/>
You can view your invoice clicking on the button below. You can view your invoice clicking on the button below.
</td> </td>
@ -114,7 +114,7 @@
<w:anchorlock/> <w:anchorlock/>
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center> <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
</v:roundrect> </v:roundrect>
<![endif]--><a href="{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a> <![endif]--><a href="{{ base_url }}{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -0,0 +1,13 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ base_url }}{% url 'hosting:reset_password_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

View File

@ -0,0 +1,13 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ base_url }}{% url 'hosting:reset_password_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

View File

@ -110,7 +110,7 @@
<w:anchorlock/> <w:anchorlock/>
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center> <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
</v:roundrect> </v:roundrect>
<![endif]--><a href="{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a> <![endif]--><a href="{{ base_url }}{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -110,7 +110,7 @@
<w:anchorlock/> <w:anchorlock/>
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center> <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
</v:roundrect> </v:roundrect>
<![endif]--><a href="{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a> <![endif]--><a href="{{ base_url }}{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -111,7 +111,7 @@
<w:anchorlock/> <w:anchorlock/>
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center> <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
</v:roundrect> </v:roundrect>
<![endif]--><a href="{{request.HOS}}{% url 'hosting:virtual_machines' vm.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">VM Dashboard</a> <![endif]--><a href="{{base_url}}{% url 'hosting:virtual_machines' vm.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">VM Dashboard</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -111,7 +111,7 @@
<w:anchorlock/> <w:anchorlock/>
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center> <center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
</v:roundrect> </v:roundrect>
<![endif]--><a href="{{request.HOS}}{% url 'hosting:virtual_machines' vm.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">VM Dashboard</a> <![endif]--><a href="{{base_url}}{% url 'hosting:virtual_machines' vm.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">VM Dashboard</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -53,7 +53,7 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand topnav" href="{% url 'ungleich_page:landing' %}"><img src="{% static 'hosting/img/logo_black.svg' %}"></a> <a class="navbar-brand topnav" href="{{ request.session.hosting_url}}"><img src="{% static 'hosting/img/logo_black.svg' %}"></a>
</div> </div>
<!-- Collect the nav links, forms, and other content for toggling --> <!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

View File

@ -0,0 +1,38 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3%}
{% block content %}
<div class="intro-auth intro-reset-password">
<div class="container">
<div class="col-md-4">&nbsp;</div>
<div class="col-md-4">
<div class="intro-message">
{% if messages %}
<ul class="list-unstyled">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<h2 class="section-heading">Set your new password</h2>
<form action="" method="post" class="form" novalidate>
{% csrf_token %}
{% for field in form %}
{% bootstrap_field field show_label=False %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-default">
Reset
</button>
{% endbuttons %}
</form>
<span>Already have an account ? <a class="unlink" href="{% url 'hosting:login' %}">Log in</a></span>
<ul class="list-inline intro-social-buttons">
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -6,6 +6,14 @@
<div class="container"> <div class="container">
<div class="col-md-4 col-md-offset-4"> <div class="col-md-4 col-md-offset-4">
{% if messages %}
<ul class="list-unstyled">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% block messages %} {% block messages %}
{% if request.GET.logged_out %} {% if request.GET.logged_out %}
<div class="alert"> <!-- singular --> <div class="alert"> <!-- singular -->
@ -31,6 +39,8 @@
{% endbuttons %} {% endbuttons %}
</form> </form>
<span>Don't have an account yet ? <a class="unlink" href="{% url 'hosting:signup' %}">Sign up</a></span> <span>Don't have an account yet ? <a class="unlink" href="{% url 'hosting:signup' %}">Sign up</a></span>
<br/>
<span> <a class="unlink" href="{% url 'hosting:reset_password' %}">Forgot your password ?</a></span>
<ul class="list-inline intro-social-buttons"> <ul class="list-inline intro-social-buttons">

View File

@ -0,0 +1,29 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3%}
{% block content %}
<div class="intro-auth intro-reset-password">
<div class="container">
<div class="col-md-4">&nbsp;</div>
<div class="col-md-4">
<div class="intro-message">
<h2 class="section-heading">Reset your password</h2>
<form action="{% url 'hosting:reset_password' %}" method="post" class="form" novalidate>
{% csrf_token %}
{% for field in form %}
{% bootstrap_field field show_label=False %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-default">
Reset
</button>
{% endbuttons %}
</form>
<span>Already have an account ? <a class="unlink" href="{% url 'hosting:login' %}">Log in</a></span>
<ul class="list-inline intro-social-buttons">
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -3,8 +3,8 @@
{% block content %} {% block content %}
<div class="intro-auth intro-signup"> <div class="intro-auth intro-signup">
<div class="container"> <div class="container">
<div class="col-md-4">&nbsp;</div> <div class="col-md-4 col-sm-4 col-xs-4">&nbsp;</div>
<div class="col-md-4"> <div class="col-md-4 col-sm-6 col-xs-6">
<div class="intro-message"> <div class="intro-message">
<h2 class="section-heading">Sign up</h2> <h2 class="section-heading">Sign up</h2>

View File

@ -10,7 +10,7 @@ from model_mommy import mommy
from membership.models import CustomUser, StripeCustomer from membership.models import CustomUser, StripeCustomer
from .models import VirtualMachineType, HostingOrder, VirtualMachinePlan from .models import VirtualMachineType, HostingOrder, VirtualMachinePlan
from .views import DjangoHostingView, RailsHostingView, NodeJSHostingView, LoginView, SignupView, \ from .views import DjangoHostingView, RailsHostingView, NodeJSHostingView, LoginView, SignupView, \
PaymentVMView, OrdersHostingDetailView, OrdersHostingListView, VirtualMachineDetailView, \ PaymentVMView, OrdersHostingDetailView, OrdersHostingListView, VirtualMachineView, \
VirtualMachinesPlanListView VirtualMachinesPlanListView
from utils.tests import BaseTestCase from utils.tests import BaseTestCase
@ -172,16 +172,16 @@ class PaymentVMViewTest(BaseTestCase):
settings.STRIPE_API_PUBLIC_KEY) settings.STRIPE_API_PUBLIC_KEY)
class VirtualMachineDetailViewTest(BaseTestCase): class VirtualMachineViewTest(BaseTestCase):
def setUp(self): def setUp(self):
super(VirtualMachineDetailViewTest, self).setUp() super(VirtualMachineViewTest, self).setUp()
self.stripe_customer = mommy.make(StripeCustomer, user=self.customer) self.stripe_customer = mommy.make(StripeCustomer, user=self.customer)
self.vm = mommy.make(VirtualMachinePlan) self.vm = mommy.make(VirtualMachinePlan)
self.order = mommy.make(HostingOrder, customer=self.stripe_customer, vm_plan=self.vm) self.order = mommy.make(HostingOrder, customer=self.stripe_customer, vm_plan=self.vm)
self.url = reverse('hosting:virtual_machines', kwargs={'pk': self.vm.id}) self.url = reverse('hosting:virtual_machines', kwargs={'pk': self.vm.id})
self.view = VirtualMachineDetailView() self.view = VirtualMachineView()
self.expected_template = 'hosting/virtual_machine_detail.html' self.expected_template = 'hosting/virtual_machine_detail.html'
def url_resolve_to_view_correctly(self): def url_resolve_to_view_correctly(self):

View File

@ -4,7 +4,7 @@ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
NodeJSHostingView, LoginView, SignupView, IndexView, \ NodeJSHostingView, LoginView, SignupView, IndexView, \
OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\ OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \ VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \
MarkAsReadNotificationView MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView
urlpatterns = [ urlpatterns = [
url(r'index/?$', IndexView.as_view(), name='index'), url(r'index/?$', IndexView.as_view(), name='index'),
@ -27,6 +27,9 @@ urlpatterns = [
name='read_notification'), name='read_notification'),
url(r'login/?$', LoginView.as_view(), name='login'), url(r'login/?$', LoginView.as_view(), name='login'),
url(r'signup/?$', SignupView.as_view(), name='signup'), url(r'signup/?$', SignupView.as_view(), name='signup'),
url(r'reset-password/?$', PasswordResetView.as_view(), name='reset_password'),
url(r'reset-password-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
PasswordResetConfirmView.as_view(), name='reset_password_confirm'),
url(r'^logout/?$', 'django.contrib.auth.views.logout', url(r'^logout/?$', 'django.contrib.auth.views.logout',
{'next_page': '/hosting/login?logged_out=true'}, name='logout') {'next_page': '/hosting/login?logged_out=true'}, name='logout')
] ]

View File

@ -4,6 +4,10 @@ from django.core.urlresolvers import reverse_lazy, reverse
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import View, CreateView, FormView, ListView, DetailView,\ from django.views.generic import View, CreateView, FormView, ListView, DetailView,\
DeleteView, TemplateView, UpdateView DeleteView, TemplateView, UpdateView
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib import messages
from django.utils.encoding import force_bytes
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from django.conf import settings from django.conf import settings
@ -16,7 +20,7 @@ from stored_messages.api import mark_read
from membership.models import CustomUser, StripeCustomer from membership.models import CustomUser, StripeCustomer
from utils.stripe_utils import StripeUtils from utils.stripe_utils import StripeUtils
from utils.forms import BillingAddressForm from utils.forms import BillingAddressForm, PasswordResetRequestForm, SetPasswordForm
from utils.mailer import BaseEmail from utils.mailer import BaseEmail
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder
from .forms import HostingUserSignupForm, HostingUserLoginForm from .forms import HostingUserSignupForm, HostingUserLoginForm
@ -164,6 +168,71 @@ class SignupView(CreateView):
return HttpResponseRedirect(self.get_success_url()) return HttpResponseRedirect(self.get_success_url())
class PasswordResetView(FormView):
template_name = 'hosting/reset_password.html'
form_class = PasswordResetRequestForm
success_message = "The link to reset your email has been sent to your email"
success_url = reverse_lazy('hosting:login')
# form_valid_message = 'Thank you for registering'
def form_valid(self, form):
email = form.cleaned_data.get('email')
user = CustomUser.objects.get(email=email)
messages.add_message(self.request, messages.SUCCESS, self.success_message)
context = {
'user': user,
'token': default_token_generator.make_token(user),
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'site_name': 'ungleich',
'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host())
}
email_data = {
'subject': 'Password Reset',
'to': email,
'context': context,
'template_name': 'password_reset_email',
'template_path': 'emails/'
}
email = BaseEmail(**email_data)
email.send()
return HttpResponseRedirect(self.get_success_url())
class PasswordResetConfirmView(FormView):
template_name = 'hosting/confirm_reset_password.html'
form_class = SetPasswordForm
success_url = reverse_lazy('hosting:login')
def post(self, request, uidb64=None, token=None, *arg, **kwargs):
try:
uid = urlsafe_base64_decode(uidb64)
user = CustomUser.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
user = None
form = self.form_class(request.POST)
if user is not None and default_token_generator.check_token(user, token):
if form.is_valid():
new_password = form.cleaned_data['new_password2']
user.set_password(new_password)
user.save()
messages.success(request, 'Password has been reset.')
return self.form_valid(form)
else:
messages.error(request, 'Password reset has not been unsuccessful.')
return self.form_invalid(form)
else:
messages.error(request, 'The reset password link is no longer valid.')
return self.form_invalid(form)
class NotificationsView(TemplateView): class NotificationsView(TemplateView):
template_name = 'hosting/notifications.html' template_name = 'hosting/notifications.html'
@ -285,13 +354,16 @@ class PaymentVMView(LoginRequiredMixin, FormView):
# Send notification to ungleich as soon as VM has been booked # Send notification to ungleich as soon as VM has been booked
# TODO send email using celery # TODO send email using celery
context = { context = {
'vm': plan, 'vm': plan,
'order': order 'order': order,
'base_url': "{0}://{1}".format(request.scheme, request.get_host())
} }
email_data = { email_data = {
'subject': 'New VM request', 'subject': 'New VM request',
'to': 'info@ungleich.ch', 'to': request.user.email,
'context': context, 'context': context,
'template_name': 'new_booked_vm', 'template_name': 'new_booked_vm',
'template_path': 'emails/' 'template_path': 'emails/'
@ -299,11 +371,6 @@ class PaymentVMView(LoginRequiredMixin, FormView):
email = BaseEmail(**email_data) email = BaseEmail(**email_data)
email.send() email.send()
# request.session.update({
# 'charge': charge,
# 'order': order.id,
# 'billing_address': billing_address.id
# })
return HttpResponseRedirect(reverse('hosting:orders', kwargs={'pk': order.id})) return HttpResponseRedirect(reverse('hosting:orders', kwargs={'pk': order.id}))
else: else:
return self.form_invalid(form) return self.form_invalid(form)
@ -368,7 +435,8 @@ class VirtualMachineView(LoginRequiredMixin, UpdateView):
vm.cancel_plan() vm.cancel_plan()
context = { context = {
'vm': vm 'vm': vm,
'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host())
} }
email_data = { email_data = {
'subject': 'Virtual machine plan canceled', 'subject': 'Virtual machine plan canceled',

View File

@ -1,4 +1,4 @@
{% load cms_tags menu_tags sekizai_tags staticfiles bootstrap3 %} {% load i18n cms_tags menu_tags sekizai_tags staticfiles bootstrap3 %}
<!doctype html> <!doctype html>
<html> <html>
<head> <head>

View File

@ -3,9 +3,52 @@ from .models import ContactMessage, BillingAddress
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives from django.core.mail import EmailMultiAlternatives
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from membership.models import CustomUser
# from utils.fields import CountryField # from utils.fields import CountryField
class PasswordResetRequestForm(forms.Form):
email = forms.CharField(widget=forms.EmailInput())
class Meta:
fields = ['email']
def clean_email(self):
email = self.cleaned_data.get('email')
try:
CustomUser.objects.get(email=email)
return email
except CustomUser.DoesNotExist:
raise forms.ValidationError("User does not exist")
else:
return email
class SetPasswordForm(forms.Form):
"""
A form that lets a user change set their password without entering the old
password
"""
error_messages = {
'password_mismatch': ("The two password fields didn't match."),
}
new_password1 = forms.CharField(label=("New password"),
widget=forms.PasswordInput)
new_password2 = forms.CharField(label=("New password confirmation"),
widget=forms.PasswordInput)
def clean_new_password2(self):
password1 = self.cleaned_data.get('new_password1')
password2 = self.cleaned_data.get('new_password2')
if password1 and password2:
if password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',)
return password2
class BillingAddressForm(forms.ModelForm): class BillingAddressForm(forms.ModelForm):
token = forms.CharField(widget=forms.HiddenInput()) token = forms.CharField(widget=forms.HiddenInput())

View File

@ -21,7 +21,7 @@ class BaseEmail(object):
self.email = EmailMultiAlternatives(self.subject, text_content) self.email = EmailMultiAlternatives(self.subject, text_content)
self.email.attach_alternative(html_content, "text/html") self.email.attach_alternative(html_content, "text/html")
self.email.to = ['info@digitalglarus.ch'] self.email.to = ['levinoelvm@gmail.com']
def send(self): def send(self):
self.email.send() self.email.send()