Merge branch 'develop' into feature/hosting_permission
This commit is contained in:
		
				commit
				
					
						f024841c4e
					
				
			
		
					 24 changed files with 638 additions and 61 deletions
				
			
		| 
						 | 
				
			
			@ -80,9 +80,8 @@ def blog(request):
 | 
			
		|||
 | 
			
		||||
def blog_detail(request, slug):
 | 
			
		||||
    # post = Post.objects.filter_by_language(get_language()).filter(slug=slug).first()
 | 
			
		||||
    language = 'en-us' # currently nothing is translated to german so we give then en
 | 
			
		||||
 | 
			
		||||
    post = Post.objects.translated(language, slug=slug).first()
 | 
			
		||||
    post = Post.objects.translated(get_language(), slug=slug).first()
 | 
			
		||||
    context = {
 | 
			
		||||
        'post': post,
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,7 +137,8 @@ TEMPLATES = [
 | 
			
		|||
                 os.path.join(PROJECT_DIR, 'hosting/templates/'),
 | 
			
		||||
                 os.path.join(PROJECT_DIR, 'ungleich/templates/djangocms_blog/'),
 | 
			
		||||
                 os.path.join(PROJECT_DIR, 'ungleich/templates/cms/ungleichch'),
 | 
			
		||||
                 os.path.join(PROJECT_DIR, 'ungleich/templates/ungleich')
 | 
			
		||||
                 os.path.join(PROJECT_DIR, 'ungleich/templates/ungleich'),
 | 
			
		||||
                 os.path.join(PROJECT_DIR, 'ungleich_page/templates/ungleich_page')
 | 
			
		||||
 | 
			
		||||
                 ],
 | 
			
		||||
        'APP_DIRS': True,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,10 @@ from django.conf.urls.static import static
 | 
			
		|||
from django.conf import settings
 | 
			
		||||
from hosting.views import RailsHostingView, DjangoHostingView, NodeJSHostingView
 | 
			
		||||
from membership import urls as membership_urls
 | 
			
		||||
from ungleich_page.views import LandingView
 | 
			
		||||
import debug_toolbar
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
urlpatterns = [   url(r'^index.html$', LandingView.as_view()),
 | 
			
		||||
                  url(r'^hosting/', include('hosting.urls', namespace="hosting")),
 | 
			
		||||
                  url(r'^railshosting/', RailsHostingView.as_view(), name="rails.hosting"),
 | 
			
		||||
                  url(r'^nodehosting/', NodeJSHostingView.as_view(), name="node.hosting"),
 | 
			
		||||
| 
						 | 
				
			
			@ -21,12 +22,13 @@ urlpatterns = [
 | 
			
		|||
 | 
			
		||||
# note the django CMS URLs included via i18n_patterns
 | 
			
		||||
urlpatterns += i18n_patterns('',
 | 
			
		||||
                             url(r'^/?$', LandingView.as_view()),
 | 
			
		||||
                             url(r'^admin/', include(admin.site.urls)),
 | 
			
		||||
                             url(r'^digitalglarus/login/', include(membership_urls)),
 | 
			
		||||
                             url(r'^digitalglarus/', include('digitalglarus.urls',
 | 
			
		||||
                                                             namespace="digitalglarus")),
 | 
			
		||||
                             # url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
 | 
			
		||||
                             url(r'^ungleich_page/',
 | 
			
		||||
                             #url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
 | 
			
		||||
                             url(r'^',
 | 
			
		||||
                                 include('ungleich_page.urls', namespace='ungleich_page'),
 | 
			
		||||
                                 name='ungleich_page'),
 | 
			
		||||
                             url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,9 @@ class HostingOrderAdminForm(forms.ModelForm):
 | 
			
		|||
            raise forms.ValidationError("""You can't make a charge over
 | 
			
		||||
                                         a canceled virtual machine plan""")
 | 
			
		||||
 | 
			
		||||
        if not customer:
 | 
			
		||||
            raise forms.ValidationError("""You need select a costumer""")
 | 
			
		||||
 | 
			
		||||
        # Make a charge to the customer
 | 
			
		||||
        stripe_utils = StripeUtils()
 | 
			
		||||
        charge_response = stripe_utils.make_charge(customer=customer.stripe_id,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,21 @@
 | 
			
		|||
from django.shortcuts import redirect
 | 
			
		||||
from django.core.urlresolvers import reverse
 | 
			
		||||
from .models import VirtualMachinePlan
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProcessVMSelectionMixin(object):
 | 
			
		||||
 | 
			
		||||
    def post(self, request, *args, **kwargs):
 | 
			
		||||
        hosting = request.POST.get('configuration')
 | 
			
		||||
        configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(hosting)
 | 
			
		||||
        vm_specs = {
 | 
			
		||||
            'cores': request.POST.get('cores'),
 | 
			
		||||
            'memory': request.POST.get('memory'),
 | 
			
		||||
            'disk_size': request.POST.get('disk_space'),
 | 
			
		||||
            'hosting_company': request.POST.get('hosting_company'),
 | 
			
		||||
            'location_code': request.POST.get('location_code'),
 | 
			
		||||
            'configuration': request.POST.get('configuration'),
 | 
			
		||||
            'configuration_detail': request.POST.get('configuration_detail'),
 | 
			
		||||
            'configuration': hosting,
 | 
			
		||||
            'configuration_detail': configuration_detail,
 | 
			
		||||
            'final_price': request.POST.get('final_price')
 | 
			
		||||
        }
 | 
			
		||||
        request.session['vm_specs'] = vm_specs
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _
 | 
			
		|||
from django.utils.functional import cached_property
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from Crypto.PublicKey import RSA
 | 
			
		||||
from stored_messages.settings import stored_messages_settings
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +173,7 @@ class VirtualMachinePlan(AssignPermissionsMixin, models.Model):
 | 
			
		|||
        private_key, public_key = self.generate_RSA()
 | 
			
		||||
        self.public_key = public_key
 | 
			
		||||
        self.save(update_fields=['public_key'])
 | 
			
		||||
        return private_key
 | 
			
		||||
        return private_key, public_key
 | 
			
		||||
 | 
			
		||||
    def cancel_plan(self):
 | 
			
		||||
        self.status = self.CANCELED_STATUS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
{% load static from staticfiles %}
 | 
			
		||||
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
{% load static from staticfiles %}
 | 
			
		||||
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										44
									
								
								hosting/templates/hosting/hosting_pricing.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								hosting/templates/hosting/hosting_pricing.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
{% load staticfiles %}
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
	<link href="{% static 'hosting/css/pricing.css' %}" rel="stylesheet" />
 | 
			
		||||
	<title>Hosting</title>
 | 
			
		||||
    <!-- Bootstrap Core CSS -->
 | 
			
		||||
    <link href="{% static 'hosting/css/bootstrap.min.css' %}" rel="stylesheet">
 | 
			
		||||
 | 
			
		||||
    <link href="{% static 'hosting/css/pricing.css' %}" rel="stylesheet">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <!-- Custom CSS -->
 | 
			
		||||
    <link href="{% static 'hosting/css/landing-page.css' %}" rel="stylesheet">
 | 
			
		||||
 | 
			
		||||
    <!-- Custom Fonts -->
 | 
			
		||||
    <link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
 | 
			
		||||
    <link href="{% static 'hosting/font-awesome/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
 | 
			
		||||
    <link href="//fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
 | 
			
		||||
    <link rel="shortcut icon" href="{% static 'hosting/img/favicon.ico' %}" type="image/x-icon" />
 | 
			
		||||
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
	{% include "hosting/includes/_pricing.html" with select_configuration=True%}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <!-- Pricing data -->
 | 
			
		||||
    {% if vm_types %}
 | 
			
		||||
    <script type="text/javascript"> 
 | 
			
		||||
         (function () {window.VMTypesData = "{{vm_types|safe}}";})();
 | 
			
		||||
    </script>
 | 
			
		||||
    {%endif%}
 | 
			
		||||
 | 
			
		||||
    <!-- Lodash -->
 | 
			
		||||
    <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.1/lodash.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- jQuery -->
 | 
			
		||||
    <script src="{% static 'hosting/js/jquery.js' %}"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Pricing -->
 | 
			
		||||
    <script src="{% static 'hosting/js/pricing.js' %}"></script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -24,8 +24,7 @@
 | 
			
		|||
                {% csrf_token %}
 | 
			
		||||
                <input type="hidden" name="hosting_company" value="{{vm.hosting_company}}">
 | 
			
		||||
                <input type="hidden" name="location_code" value="{{vm.location_code}}">
 | 
			
		||||
                <input type="hidden" name="configuration_detail" value="{{configuration_detail}}">
 | 
			
		||||
                <input type="hidden" name="configuration" value="{{hosting}}">
 | 
			
		||||
               
 | 
			
		||||
                
 | 
			
		||||
                
 | 
			
		||||
                <ul class="pricing {% cycle 'p-red' 'p-black' 'p-red' 'p-yel' %}">
 | 
			
		||||
| 
						 | 
				
			
			@ -46,13 +45,24 @@
 | 
			
		|||
                    </div>
 | 
			
		||||
                  </li>
 | 
			
		||||
                  <li>
 | 
			
		||||
                    <!-- Single button -->
 | 
			
		||||
                    <div class="btn-group">
 | 
			
		||||
                      <div class="form-group">
 | 
			
		||||
                        <label for="cores">Configuration: </label>
 | 
			
		||||
                        {{configuration_detail}}
 | 
			
		||||
                  <label for="configuration">Configuration: </label>
 | 
			
		||||
                    {% if select_configuration %}
 | 
			
		||||
                        <select class="form-control" name="configuration" id="{{vm.hosting_company}}-configuration" data-vm-type="{{vm.hosting_company}}">
 | 
			
		||||
                        {% for key,value in configuration_options.items   %}
 | 
			
		||||
                            <option  value="{{key}}">{{ value }}</option>
 | 
			
		||||
                        {% endfor %}
 | 
			
		||||
                        </select>
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                      <input type="hidden" name="configuration_detail" value="{{configuration_detail}}">
 | 
			
		||||
                      <input type="hidden" name="configuration" value="{{hosting}}">
 | 
			
		||||
                      <!-- Single button -->
 | 
			
		||||
                      <div class="btn-group">
 | 
			
		||||
                        <div class="form-group">
 | 
			
		||||
                          <label>Configuration: </label>
 | 
			
		||||
                          {{configuration_detail}}
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                  </li>
 | 
			
		||||
                  <li>
 | 
			
		||||
                    <!-- Single button -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,6 +89,11 @@
 | 
			
		|||
								    </div><!--/row-->    
 | 
			
		||||
								  </div><!--/col-12-->
 | 
			
		||||
								</div><!--/row-->
 | 
			
		||||
								<div class="row">
 | 
			
		||||
									<div class="col-md-12">
 | 
			
		||||
										Configuration: {{virtual_machine.get_configuration_display}}
 | 
			
		||||
									</div>
 | 
			
		||||
								</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				            </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										116
									
								
								hosting/test_forms.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								hosting/test_forms.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,116 @@
 | 
			
		|||
from django.test import TestCase
 | 
			
		||||
 | 
			
		||||
from unittest import mock
 | 
			
		||||
from model_mommy import mommy
 | 
			
		||||
 | 
			
		||||
from .forms import HostingOrderAdminForm, HostingUserLoginForm, HostingUserSignupForm
 | 
			
		||||
from .models import VirtualMachinePlan
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HostingUserLoginFormTest(TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        password = 'user_password'
 | 
			
		||||
        self.user = mommy.make('CustomUser')
 | 
			
		||||
 | 
			
		||||
        self.user.set_password(password)
 | 
			
		||||
        self.user.save()
 | 
			
		||||
        self.completed_data = {
 | 
			
		||||
            'email': self.user.email,
 | 
			
		||||
            'password': password
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.incorrect_data = {
 | 
			
		||||
            'email': 'test',
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def test_valid_form(self):
 | 
			
		||||
        form = HostingUserLoginForm(data=self.completed_data)
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
 | 
			
		||||
    def test_invalid_form(self):
 | 
			
		||||
        form = HostingUserLoginForm(data=self.incorrect_data)
 | 
			
		||||
        self.assertFalse(form.is_valid())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HostingUserSignupFormTest(TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
 | 
			
		||||
        self.completed_data = {
 | 
			
		||||
            'name': 'test name',
 | 
			
		||||
            'email': 'test@ungleich.com',
 | 
			
		||||
            'password': 'test_password',
 | 
			
		||||
            'confirm_password': 'test_password'
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.incorrect_data = {
 | 
			
		||||
            'email': 'test',
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def test_valid_form(self):
 | 
			
		||||
        form = HostingUserSignupForm(data=self.completed_data)
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
 | 
			
		||||
    def test_invalid_form(self):
 | 
			
		||||
        form = HostingUserSignupForm(data=self.incorrect_data)
 | 
			
		||||
        self.assertFalse(form.is_valid())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HostingOrderAdminFormTest(TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
 | 
			
		||||
        self.customer = mommy.make('StripeCustomer')
 | 
			
		||||
        self.vm_plan = mommy.make('VirtualMachinePlan')
 | 
			
		||||
        self.vm_canceled_plan = mommy.make('VirtualMachinePlan',
 | 
			
		||||
                                           status=VirtualMachinePlan.CANCELED_STATUS)
 | 
			
		||||
 | 
			
		||||
        self.mocked_charge = {
 | 
			
		||||
            'amount': 5100,
 | 
			
		||||
            'amount_refunded': 0,
 | 
			
		||||
            'balance_transaction': 'txn_18U99zGjsLAXdRPzUJKkBx3Q',
 | 
			
		||||
            'captured': True,
 | 
			
		||||
            'created': 1467785123,
 | 
			
		||||
            'currency': 'chf',
 | 
			
		||||
            'customer': 'cus_8V61MvJvMd0PhM',
 | 
			
		||||
            'status': 'succeeded'
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.completed_data = {
 | 
			
		||||
            'customer': self.customer.id,
 | 
			
		||||
            'vm_plan': self.vm_plan.id,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.incompleted_data = {
 | 
			
		||||
            'vm_plan': self.vm_plan.id,
 | 
			
		||||
            'customer': None
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    @mock.patch('utils.stripe_utils.StripeUtils.make_charge')
 | 
			
		||||
    def test_valid_form(self, stripe_mocked_call):
 | 
			
		||||
        stripe_mocked_call.return_value = {
 | 
			
		||||
            'paid': True,
 | 
			
		||||
            'response_object': self.mocked_charge,
 | 
			
		||||
            'error': None
 | 
			
		||||
        }
 | 
			
		||||
        form = HostingOrderAdminForm(data=self.completed_data)
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
 | 
			
		||||
    @mock.patch('utils.stripe_utils.StripeUtils.make_charge')
 | 
			
		||||
    def test_invalid_form_canceled_vm(self, stripe_mocked_call):
 | 
			
		||||
 | 
			
		||||
        self.completed_data.update({
 | 
			
		||||
            'vm_plan': self.vm_canceled_plan.id
 | 
			
		||||
        })
 | 
			
		||||
        stripe_mocked_call.return_value = {
 | 
			
		||||
            'paid': True,
 | 
			
		||||
            'response_object': self.mocked_charge,
 | 
			
		||||
            'error': None
 | 
			
		||||
        }
 | 
			
		||||
        form = HostingOrderAdminForm(data=self.completed_data)
 | 
			
		||||
        self.assertFalse(form.is_valid())
 | 
			
		||||
 | 
			
		||||
    def test_invalid_form(self):
 | 
			
		||||
        form = HostingOrderAdminForm(data=self.incompleted_data)
 | 
			
		||||
        self.assertFalse(form.is_valid())
 | 
			
		||||
| 
						 | 
				
			
			@ -3,15 +3,21 @@ from django.conf import settings
 | 
			
		|||
from django.test import TestCase, RequestFactory
 | 
			
		||||
from django.core.urlresolvers import reverse
 | 
			
		||||
from django.core.urlresolvers import resolve
 | 
			
		||||
from django.contrib.auth.tokens import default_token_generator
 | 
			
		||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
 | 
			
		||||
from django.utils.encoding import force_bytes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from model_mommy import mommy
 | 
			
		||||
from stored_messages.models import Inbox
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from membership.models import CustomUser, StripeCustomer
 | 
			
		||||
from .models import VirtualMachineType, HostingOrder, VirtualMachinePlan
 | 
			
		||||
from .views import DjangoHostingView, RailsHostingView, NodeJSHostingView, LoginView, SignupView, \
 | 
			
		||||
    PaymentVMView, OrdersHostingDetailView, OrdersHostingListView, VirtualMachineView, \
 | 
			
		||||
    VirtualMachinesPlanListView
 | 
			
		||||
    VirtualMachinesPlanListView, PasswordResetView, PasswordResetConfirmView, HostingPricingView, \
 | 
			
		||||
    NotificationsView, MarkAsReadNotificationView, GenerateVMSSHKeysView
 | 
			
		||||
from utils.tests import BaseTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,9 +46,12 @@ class DjangoHostingViewTest(TestCase, ProcessVMSelectionTestMixin):
 | 
			
		|||
        self.url = reverse('django.hosting')
 | 
			
		||||
        self.view = DjangoHostingView()
 | 
			
		||||
        self.expected_template = 'hosting/django.html'
 | 
			
		||||
        HOSTING = 'django'
 | 
			
		||||
        configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
 | 
			
		||||
        self.expected_context = {
 | 
			
		||||
            'hosting': "django",
 | 
			
		||||
            'hosting': HOSTING,
 | 
			
		||||
            'hosting_long': "Django",
 | 
			
		||||
            'configuration_detail': configuration_detail,
 | 
			
		||||
            'domain': "django-hosting.ch",
 | 
			
		||||
            'google_analytics': "UA-62285904-6",
 | 
			
		||||
            'email': "info@django-hosting.ch",
 | 
			
		||||
| 
						 | 
				
			
			@ -56,9 +65,12 @@ class RailsHostingViewTest(TestCase, ProcessVMSelectionTestMixin):
 | 
			
		|||
        self.url = reverse('rails.hosting')
 | 
			
		||||
        self.view = RailsHostingView()
 | 
			
		||||
        self.expected_template = 'hosting/rails.html'
 | 
			
		||||
        HOSTING = 'rails'
 | 
			
		||||
        configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
 | 
			
		||||
        self.expected_context = {
 | 
			
		||||
            'hosting': "rails",
 | 
			
		||||
            'hosting': HOSTING,
 | 
			
		||||
            'hosting_long': "Ruby On Rails",
 | 
			
		||||
            'configuration_detail': configuration_detail,
 | 
			
		||||
            'domain': "rails-hosting.ch",
 | 
			
		||||
            'google_analytics': "UA-62285904-5",
 | 
			
		||||
            'email': "info@rails-hosting.ch",
 | 
			
		||||
| 
						 | 
				
			
			@ -72,9 +84,12 @@ class NodeJSHostingViewTest(TestCase, ProcessVMSelectionTestMixin):
 | 
			
		|||
        self.url = reverse('node.hosting')
 | 
			
		||||
        self.view = NodeJSHostingView()
 | 
			
		||||
        self.expected_template = 'hosting/nodejs.html'
 | 
			
		||||
        HOSTING = 'nodejs'
 | 
			
		||||
        configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
 | 
			
		||||
        self.expected_context = {
 | 
			
		||||
            'hosting': "nodejs",
 | 
			
		||||
            'hosting': HOSTING,
 | 
			
		||||
            'hosting_long': "NodeJS",
 | 
			
		||||
            'configuration_detail': configuration_detail,
 | 
			
		||||
            'domain': "node-hosting.ch",
 | 
			
		||||
            'google_analytics': "UA-62285904-7",
 | 
			
		||||
            'email': "info@node-hosting.ch",
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +97,36 @@ class NodeJSHostingViewTest(TestCase, ProcessVMSelectionTestMixin):
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HostingPricingViewTest(TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.url = reverse('hosting:pricing')
 | 
			
		||||
        self.view = HostingPricingView()
 | 
			
		||||
        self.expected_template = 'hosting/hosting_pricing.html'
 | 
			
		||||
 | 
			
		||||
        configuration_options = dict(VirtualMachinePlan.VM_CONFIGURATION)
 | 
			
		||||
        self.expected_context = {
 | 
			
		||||
            'configuration_options': configuration_options,
 | 
			
		||||
            'email': "info@django-hosting.ch",
 | 
			
		||||
            'vm_types': VirtualMachineType.get_serialized_vm_types(),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def url_resolve_to_view_correctly(self):
 | 
			
		||||
        found = resolve(self.url)
 | 
			
		||||
        self.assertEqual(found.func.__name__, self.view.__name__)
 | 
			
		||||
 | 
			
		||||
    def get(self):
 | 
			
		||||
        response = self.client.get(self.url)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        self.assertEqual(self.view.get_context_data(), self.expected_context)
 | 
			
		||||
        self.assertTemplateUsed(response, self.expected_template)
 | 
			
		||||
 | 
			
		||||
    def test_anonymous_post(self):
 | 
			
		||||
        response = self.client.post(self.url)
 | 
			
		||||
        self.assertRedirects(response, expected_url=reverse('hosting:login'),
 | 
			
		||||
                             status_code=302, target_status_code=200)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PaymentVMViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -115,6 +160,7 @@ class PaymentVMViewTest(BaseTestCase):
 | 
			
		|||
                'memory': 10,
 | 
			
		||||
                'disk_size': 10000,
 | 
			
		||||
                'price': 22000,
 | 
			
		||||
                'configuration': dict(VirtualMachinePlan.VM_CONFIGURATION).get('django')
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +199,8 @@ class PaymentVMViewTest(BaseTestCase):
 | 
			
		|||
            'memory': hosting_order.vm_plan.memory,
 | 
			
		||||
            'disk_size': hosting_order.vm_plan.disk_size,
 | 
			
		||||
            'price': hosting_order.vm_plan.price,
 | 
			
		||||
            'hosting_company': hosting_order.vm_plan.vm_type.hosting_company
 | 
			
		||||
            'hosting_company': hosting_order.vm_plan.vm_type.hosting_company,
 | 
			
		||||
            'configuration': hosting_order.vm_plan.configuration
 | 
			
		||||
        }
 | 
			
		||||
        self.assertEqual(vm_plan, self.session_data.get('vm_specs'))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +219,107 @@ class PaymentVMViewTest(BaseTestCase):
 | 
			
		|||
                         settings.STRIPE_API_PUBLIC_KEY)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotificationsViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(NotificationsViewTest, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.view = NotificationsView
 | 
			
		||||
        self.url = reverse('hosting:notifications')
 | 
			
		||||
        self.expected_template = 'hosting/notifications.html'
 | 
			
		||||
 | 
			
		||||
        self.inboxes = mommy.make(Inbox, user=self.customer, _quantity=2)
 | 
			
		||||
        self.messages = list(map(lambda x: x.message, self.inboxes))
 | 
			
		||||
 | 
			
		||||
    def test_url_resolve_to_view_correctly(self):
 | 
			
		||||
        found = resolve(self.url)
 | 
			
		||||
        self.assertEqual(found.func.__name__, self.view.__name__)
 | 
			
		||||
 | 
			
		||||
    def test_get(self):
 | 
			
		||||
 | 
			
		||||
        # Anonymous user should get redirect to login
 | 
			
		||||
        response = self.client.get(self.url)
 | 
			
		||||
        expected_url = "%s?next=%s" % (reverse('hosting:login'), reverse('hosting:notifications'))
 | 
			
		||||
        self.assertRedirects(response, expected_url=expected_url,
 | 
			
		||||
                             status_code=302, target_status_code=200)
 | 
			
		||||
 | 
			
		||||
        # Logged user should get the page
 | 
			
		||||
        response = self.customer_client.get(self.url, follow=True)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        self.assertEqual(response.context['all_notifications'], self.messages)
 | 
			
		||||
        self.assertTemplateUsed(response, self.expected_template)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MarkAsReadNotificationViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(MarkAsReadNotificationViewTest, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.view = MarkAsReadNotificationView
 | 
			
		||||
        self.url = reverse('hosting:notifications')
 | 
			
		||||
        self.expected_template = 'hosting/notifications.html'
 | 
			
		||||
 | 
			
		||||
        self.inbox = mommy.make(Inbox, user=self.customer)
 | 
			
		||||
        self.message = self.inbox.message
 | 
			
		||||
 | 
			
		||||
        self.url = reverse('hosting:read_notification', kwargs={'pk': self.message.id})
 | 
			
		||||
 | 
			
		||||
    def test_url_resolve_to_view_correctly(self):
 | 
			
		||||
        found = resolve(self.url)
 | 
			
		||||
        self.assertEqual(found.func.__name__, self.view.__name__)
 | 
			
		||||
 | 
			
		||||
    def test_post(self):
 | 
			
		||||
 | 
			
		||||
        # Anonymous user should get redirect to login
 | 
			
		||||
        response = self.client.get(self.url)
 | 
			
		||||
        expected_url = "%s?next=%s" % (reverse('hosting:login'),
 | 
			
		||||
                                       reverse('hosting:read_notification',
 | 
			
		||||
                                               kwargs={'pk': self.message.id}))
 | 
			
		||||
        self.assertRedirects(response, expected_url=expected_url,
 | 
			
		||||
                             status_code=302, target_status_code=200)
 | 
			
		||||
 | 
			
		||||
        # Logged user should mark a message as read
 | 
			
		||||
        response = self.customer_client.post(self.url, follow=True)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        self.assertFalse(Inbox.objects.filter(user=self.customer).exists())
 | 
			
		||||
        self.assertTemplateUsed(response, self.expected_template)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GenerateVMSSHKeysViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(GenerateVMSSHKeysViewTest, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.view = GenerateVMSSHKeysView
 | 
			
		||||
        self.vm = mommy.make(VirtualMachinePlan)
 | 
			
		||||
        self.expected_template = 'hosting/virtual_machine_key.html'
 | 
			
		||||
        self.url = reverse('hosting:virtual_machine_key', kwargs={'pk': self.vm.id})
 | 
			
		||||
 | 
			
		||||
    def test_url_resolve_to_view_correctly(self):
 | 
			
		||||
        found = resolve(self.url)
 | 
			
		||||
        self.assertEqual(found.func.__name__, self.view.__name__)
 | 
			
		||||
 | 
			
		||||
    def test_get(self):
 | 
			
		||||
 | 
			
		||||
        # Anonymous user should get redirect to login
 | 
			
		||||
        response = self.client.get(self.url)
 | 
			
		||||
        expected_url = "%s?next=%s" % (reverse('hosting:login'),
 | 
			
		||||
                                       reverse('hosting:virtual_machine_key',
 | 
			
		||||
                                               kwargs={'pk': self.vm.id}))
 | 
			
		||||
        self.assertRedirects(response, expected_url=expected_url,
 | 
			
		||||
                             status_code=302, target_status_code=200)
 | 
			
		||||
 | 
			
		||||
        # Logged user should get the page
 | 
			
		||||
        response = self.customer_client.get(self.url, follow=True)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        updated_vm = VirtualMachinePlan.objects.get(id=self.vm.id)
 | 
			
		||||
        self.assertEqual(response.context['public_key'].decode("utf-8"), updated_vm.public_key)
 | 
			
		||||
        self.assertTrue(response.context['private_key'] is not None)
 | 
			
		||||
        self.assertEqual(len(response.context['public_key']), 380)
 | 
			
		||||
        self.assertTrue(len(response.context['private_key']) is 1678 or 1674)
 | 
			
		||||
        self.assertTemplateUsed(response, self.expected_template)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VirtualMachineViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
| 
						 | 
				
			
			@ -357,3 +505,78 @@ class SignupViewTest(TestCase):
 | 
			
		|||
        self.user = CustomUser.objects.get(email=self.signup_data.get('email'))
 | 
			
		||||
        self.assertEqual(response.context['user'], self.user)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PasswordResetViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(PasswordResetViewTest, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.url = reverse('hosting:reset_password')
 | 
			
		||||
        self.view = PasswordResetView
 | 
			
		||||
        self.expected_template = 'hosting/reset_password.html'
 | 
			
		||||
        self.user = mommy.make('membership.CustomUser')
 | 
			
		||||
        self.password = 'fake_password'
 | 
			
		||||
        self.user.set_password(self.password)
 | 
			
		||||
        self.user.save()
 | 
			
		||||
 | 
			
		||||
        self.post_data = {
 | 
			
		||||
            'email': self.user.email
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def test_url_resolve_to_view_correctly(self):
 | 
			
		||||
        found = resolve(self.url)
 | 
			
		||||
        self.assertEqual(found.func.__name__, self.view.__name__)
 | 
			
		||||
 | 
			
		||||
    def test_get(self):
 | 
			
		||||
        response = self.client.get(self.url)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        self.assertTemplateUsed(response, self.expected_template)
 | 
			
		||||
 | 
			
		||||
    def test_post(self):
 | 
			
		||||
        response = self.client.post(self.url, data=self.post_data, follow=True)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
 | 
			
		||||
    def test_test_generate_email_context(self):
 | 
			
		||||
        context = self.setup_view(self.view()).\
 | 
			
		||||
            test_generate_email_context(self.user)
 | 
			
		||||
        self.assertEqual(context.get('user'), self.user)
 | 
			
		||||
        self.assertEqual(context.get('site_name'), 'ungleich')
 | 
			
		||||
        self.assertEqual(len(context.get('token')), 24)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PasswordResetConfirmViewTest(BaseTestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(PasswordResetConfirmViewTest, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.view = PasswordResetConfirmView
 | 
			
		||||
        self.expected_template = 'hosting/confirm_reset_password.html'
 | 
			
		||||
        self.user = mommy.make('membership.CustomUser')
 | 
			
		||||
        self.password = 'fake_password'
 | 
			
		||||
        self.user.set_password(self.password)
 | 
			
		||||
        self.user.save()
 | 
			
		||||
 | 
			
		||||
        self.token = default_token_generator.make_token(self.user)
 | 
			
		||||
        self.uid = urlsafe_base64_encode(force_bytes(self.user.pk))
 | 
			
		||||
        self.url = reverse('hosting:reset_password_confirm',
 | 
			
		||||
                           kwargs={'token': self.token, 'uidb64': self.uid})
 | 
			
		||||
 | 
			
		||||
        self.post_data = {
 | 
			
		||||
            'new_password1': 'new_password',
 | 
			
		||||
            'new_password2': 'new_password'
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def test_url_resolve_to_view_correctly(self):
 | 
			
		||||
        found = resolve(self.url)
 | 
			
		||||
        self.assertEqual(found.func.__name__, self.view.__name__)
 | 
			
		||||
 | 
			
		||||
    def test_get(self):
 | 
			
		||||
        response = self.client.get(self.url)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        self.assertTemplateUsed(response, self.expected_template)
 | 
			
		||||
 | 
			
		||||
    def test_post(self):
 | 
			
		||||
        response = self.client.post(self.url, data=self.post_data, follow=True)
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
        self.assertTrue(not response.context['form'].errors)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,13 +4,14 @@ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
 | 
			
		|||
    NodeJSHostingView, LoginView, SignupView, IndexView, \
 | 
			
		||||
    OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
 | 
			
		||||
    VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \
 | 
			
		||||
    MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView
 | 
			
		||||
    MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    url(r'index/?$', IndexView.as_view(), name='index'),
 | 
			
		||||
    url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'),
 | 
			
		||||
    url(r'nodejs/?$', NodeJSHostingView.as_view(), name='nodejshosting'),
 | 
			
		||||
    url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'),
 | 
			
		||||
    url(r'pricing/?$', HostingPricingView.as_view(), name='pricing'),
 | 
			
		||||
    url(r'payment/?$', PaymentVMView.as_view(), name='payment'),
 | 
			
		||||
    url(r'orders/?$', OrdersHostingListView.as_view(), name='orders'),
 | 
			
		||||
    url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,6 +99,26 @@ class NodeJSHostingView(ProcessVMSelectionMixin, View):
 | 
			
		|||
        return render(request, self.template_name, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HostingPricingView(ProcessVMSelectionMixin, View):
 | 
			
		||||
    template_name = "hosting/hosting_pricing.html"
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        configuration_options = dict(VirtualMachinePlan.VM_CONFIGURATION)
 | 
			
		||||
        context = {
 | 
			
		||||
            'configuration_options': configuration_options,
 | 
			
		||||
            'email': "info@django-hosting.ch",
 | 
			
		||||
            'vm_types': VirtualMachineType.get_serialized_vm_types(),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        request.session['hosting_url'] = reverse('hosting:djangohosting')
 | 
			
		||||
        context = self.get_context_data()
 | 
			
		||||
 | 
			
		||||
        return render(request, self.template_name, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IndexView(View):
 | 
			
		||||
    template_name = "hosting/index.html"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -175,13 +195,7 @@ class PasswordResetView(FormView):
 | 
			
		|||
    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)
 | 
			
		||||
 | 
			
		||||
    def test_generate_email_context(self, user):
 | 
			
		||||
        context = {
 | 
			
		||||
            'user': user,
 | 
			
		||||
            'token': default_token_generator.make_token(user),
 | 
			
		||||
| 
						 | 
				
			
			@ -190,6 +204,16 @@ class PasswordResetView(FormView):
 | 
			
		|||
            'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host())
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
    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 = self.test_generate_email_context(user)
 | 
			
		||||
        email_data = {
 | 
			
		||||
            'subject': 'Password Reset',
 | 
			
		||||
            'to': email,
 | 
			
		||||
| 
						 | 
				
			
			@ -226,15 +250,18 @@ class PasswordResetConfirmView(FormView):
 | 
			
		|||
                return self.form_valid(form)
 | 
			
		||||
            else:
 | 
			
		||||
                messages.error(request, 'Password reset has not been unsuccessful.')
 | 
			
		||||
                form.add_error(None, 'Password reset has not been unsuccessful.')
 | 
			
		||||
                return self.form_invalid(form)
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, 'The reset password link is no longer valid.')
 | 
			
		||||
            form.add_error(None, 'Password reset has not been unsuccessful.')
 | 
			
		||||
            return self.form_invalid(form)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotificationsView(TemplateView):
 | 
			
		||||
class NotificationsView(LoginRequiredMixin, TemplateView):
 | 
			
		||||
    template_name = 'hosting/notifications.html'
 | 
			
		||||
    login_url = reverse_lazy('hosting:login')
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super(NotificationsView, self).get_context_data(**kwargs)
 | 
			
		||||
| 
						 | 
				
			
			@ -251,6 +278,7 @@ class NotificationsView(TemplateView):
 | 
			
		|||
class MarkAsReadNotificationView(LoginRequiredMixin, UpdateView):
 | 
			
		||||
    model = Message
 | 
			
		||||
    success_url = reverse_lazy('hosting:notifications')
 | 
			
		||||
    login_url = reverse_lazy('hosting:login')
 | 
			
		||||
    fields = '__all__'
 | 
			
		||||
 | 
			
		||||
    def post(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -265,6 +293,7 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, DetailView):
 | 
			
		|||
    model = VirtualMachinePlan
 | 
			
		||||
    template_name = 'hosting/virtual_machine_key.html'
 | 
			
		||||
    success_url = reverse_lazy('hosting:orders')
 | 
			
		||||
    login_url = reverse_lazy('hosting:login')
 | 
			
		||||
    context_object_name = "virtual_machine"
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -272,9 +301,10 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, DetailView):
 | 
			
		|||
        context = super(GenerateVMSSHKeysView, self).get_context_data(**kwargs)
 | 
			
		||||
        vm = self.get_object()
 | 
			
		||||
        if not vm.public_key:
 | 
			
		||||
            private_key = vm.generate_keys()
 | 
			
		||||
            private_key, public_key = vm.generate_keys()
 | 
			
		||||
            context.update({
 | 
			
		||||
                'private_key': private_key
 | 
			
		||||
                'private_key': private_key,
 | 
			
		||||
                'public_key': public_key
 | 
			
		||||
            })
 | 
			
		||||
            return context
 | 
			
		||||
        return context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -8,7 +8,7 @@ msgid ""
 | 
			
		|||
msgstr ""
 | 
			
		||||
"Project-Id-Version: PACKAGE VERSION\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2016-04-15 19:16-0500\n"
 | 
			
		||||
"POT-Creation-Date: 2016-07-09 16:47-0500\n"
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
			
		||||
| 
						 | 
				
			
			@ -70,32 +70,32 @@ msgstr "und"
 | 
			
		|||
msgid "the story continues!"
 | 
			
		||||
msgstr "Die Geschichte geht weiter!"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:14
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:21 views.py:35
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:15
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:28 views.py:36
 | 
			
		||||
msgid "Contact Us"
 | 
			
		||||
msgstr "Kontaktieren Sie uns"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:16
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:18
 | 
			
		||||
msgid "Join us at"
 | 
			
		||||
msgstr "Schliessen Sie sich uns an"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:16
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:19
 | 
			
		||||
msgid "Digital Glarus"
 | 
			
		||||
msgstr "Digital Glarus"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:17
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:20
 | 
			
		||||
msgid "a great co-working space in the middle of Alps!"
 | 
			
		||||
msgstr "ein wunderschöner Co-Working Space mitten in den Alpen"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:17
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:21
 | 
			
		||||
msgid "You can contact us at"
 | 
			
		||||
msgstr "Sie können uns kontaktieren unter"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:20
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:26
 | 
			
		||||
msgid "or"
 | 
			
		||||
msgstr "oder"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:50
 | 
			
		||||
#: templates/ungleich_page/includes/_contact_us.html:60
 | 
			
		||||
msgid "Submit"
 | 
			
		||||
msgstr "Absenden"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -126,21 +126,24 @@ msgid ""
 | 
			
		|||
"infrastructure is powered by Free and Open Source Software like OpenNebula, "
 | 
			
		||||
"Qemu and GlusterFS."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Wir offerieren hohe Verfügbarkeit für das Hosting in Deutschland und in der "
 | 
			
		||||
"Schweiz. Unsere Infrastruktur ist unterstützt durch Free and Open  Source "
 | 
			
		||||
"Software wie OpenNebula."
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_portfolio.html:24
 | 
			
		||||
msgid "Rails Hosting"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Rails Hosting"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_portfolio.html:26
 | 
			
		||||
msgid ""
 | 
			
		||||
"Ready to go live with your Ruby on Rails application? We offer you ready-to-"
 | 
			
		||||
"deploy virtual machines or configure your existing infrastructure for Ruby "
 | 
			
		||||
"on Rails."
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Sind bereit mit ihrem Ruby on Rails Applikation live zu gehen?"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_portfolio.html:32
 | 
			
		||||
msgid " Configuration as a Service"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Konfiguration als Service"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_portfolio.html:34
 | 
			
		||||
msgid ""
 | 
			
		||||
| 
						 | 
				
			
			@ -148,11 +151,23 @@ msgid ""
 | 
			
		|||
"experienced team that configure your systems to provide service like DNS, E-"
 | 
			
		||||
"Mail, Databases or Webservers."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Sie brauchen eine Konfiguration? Mit ungleich haben sie ein erfahrenes Team "
 | 
			
		||||
"gefunden, dass ihnen die Konfiguration von DNS, E-Mail, Datenbanken oder "
 | 
			
		||||
"Webservern für ihr System anbietet"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:8
 | 
			
		||||
msgid "our services"
 | 
			
		||||
msgstr "Unsere Dienstleistungen"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:9
 | 
			
		||||
msgid "We support our clients in all areas of Unix infrastructure."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:10
 | 
			
		||||
msgid ""
 | 
			
		||||
"Our top notch configuration management is refreshingly simple and reliable."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:18
 | 
			
		||||
msgid "Hosting"
 | 
			
		||||
msgstr "Hosting"
 | 
			
		||||
| 
						 | 
				
			
			@ -162,6 +177,8 @@ msgid ""
 | 
			
		|||
"Ruby on Rails. Java hosting, Django hosting, we make it everything run "
 | 
			
		||||
"smooth and safe."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Ruby on Rails. Java hosting, Django hosting, wir garantieren einen "
 | 
			
		||||
"reibungslosen Ablauf"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:28
 | 
			
		||||
msgid "Configuration as a Service"
 | 
			
		||||
| 
						 | 
				
			
			@ -173,16 +190,21 @@ msgid ""
 | 
			
		|||
"needs to configured, we provide comprehensive solutions. Amazon, rackspace "
 | 
			
		||||
"or bare metal servers, we configure for you."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Ruby on Rails, Django, Java, Webserver, Mailserver, jegliche Infrastruktur "
 | 
			
		||||
"welche eine Konfiguration braucht, wir offerieren umfassende Lösungen, "
 | 
			
		||||
"Amazon, Rackspace oder Bare Metal Servers, wir konfigurieren alles."
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:38
 | 
			
		||||
msgid "Linux System Engineering"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Linux System Engineering"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_services.html:41
 | 
			
		||||
msgid ""
 | 
			
		||||
"Let your developers develop! We take care of your system administration. "
 | 
			
		||||
"Gentoo, Archlinux, Debian, Ubuntu, and many more."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Lassen sie ihre Entwickler entwickeln! Wir kümmern uns um ihre "
 | 
			
		||||
"Systemadministration. Gentoo, Archlinux, Debian, Ubuntu und viele mehr."
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_team.html:8
 | 
			
		||||
msgid "Why ungleich?*"
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +212,7 @@ msgstr "Warum ungleich?"
 | 
			
		|||
 | 
			
		||||
#: templates/ungleich_page/includes/_team.html:9
 | 
			
		||||
msgid "What our customers say"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Was unsere Kunden sagen"
 | 
			
		||||
 | 
			
		||||
#: templates/ungleich_page/includes/_team.html:29
 | 
			
		||||
msgid ""
 | 
			
		||||
| 
						 | 
				
			
			@ -249,16 +271,19 @@ msgstr ""
 | 
			
		|||
 | 
			
		||||
#: templates/ungleich_page/includes/_team.html:95
 | 
			
		||||
msgid "*ungleich means not equal to (≠) U+2260."
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "*ungleich bedeutet nicht gleich wie (≠) U+2260."
 | 
			
		||||
 | 
			
		||||
#: urls.py:7
 | 
			
		||||
msgid "contact/?$"
 | 
			
		||||
msgstr ""
 | 
			
		||||
#: urls.py:8
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Contact Us"
 | 
			
		||||
msgid "contact/$"
 | 
			
		||||
msgstr "Kontaktieren Sie uns"
 | 
			
		||||
 | 
			
		||||
#: views.py:25
 | 
			
		||||
#: views.py:26
 | 
			
		||||
msgid "Message Successfully Sent"
 | 
			
		||||
msgstr "Nachricht erfolgreich versendet"
 | 
			
		||||
 | 
			
		||||
#: views.py:36
 | 
			
		||||
#: views.py:37
 | 
			
		||||
msgid "If you have any question, just send us an email."
 | 
			
		||||
msgstr "Wenn Sie irgendwelche Fragen haben, schicken Sie uns einfach eine E-Mail."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Wenn Sie irgendwelche Fragen haben, schicken Sie uns einfach eine E-Mail."
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										28
									
								
								ungleich_page/static/ungleich_page/css/404.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ungleich_page/static/ungleich_page/css/404.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
.error {
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.error-code {
 | 
			
		||||
  bottom: 60%;
 | 
			
		||||
  color: #2d353c;
 | 
			
		||||
  font-size: 96px;
 | 
			
		||||
  line-height: 100px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.error-desc {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: #647788;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.m-b-10 {
 | 
			
		||||
  margin-bottom: 10px!important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.m-b-20 {
 | 
			
		||||
  margin-bottom: 20px!important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.m-t-20 {
 | 
			
		||||
  margin-top: 20px!important;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								ungleich_page/templates/ungleich_page/404.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								ungleich_page/templates/ungleich_page/404.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
{% load staticfiles%}
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <link href="{% static 'ungleich_page/css/404.css' %}" rel="stylesheet">
 | 
			
		||||
        <title>404 | ungleich</title>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
 | 
			
		||||
        <div class="error">
 | 
			
		||||
            <div class="error-code m-b-10 m-t-20">404 <i class="fa fa-warning"></i></div>
 | 
			
		||||
            <h3 class="font-bold">We couldn't find the page..</h3>
 | 
			
		||||
 | 
			
		||||
            <div class="error-desc">
 | 
			
		||||
                Sorry, but the page you are looking for was either not found or does not exist. <br/>
 | 
			
		||||
                Try refreshing the page or click the button below to go back to the Homepage.
 | 
			
		||||
                <div>
 | 
			
		||||
                    <a class=" login-detail-panel-button btn" href="{% url 'ungleich_page:landing' %}">
 | 
			
		||||
                            <i class="fa fa-arrow-left"></i>
 | 
			
		||||
                            Go back to Homepage                        
 | 
			
		||||
                        </a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +6,7 @@
 | 
			
		|||
		<div class="row">
 | 
			
		||||
		  <div class="col-lg-12 text-center wow fadeInDown">
 | 
			
		||||
		    <h2 class="section-heading">{% trans "our services" %}</h2>
 | 
			
		||||
		    <h3 class="section-subheading text-muted">We support our clients in all areas of Unix infrastructure.<p></p>
 | 
			
		||||
		      Our top notch configuration management is refreshingly simple and reliable."</h3>
 | 
			
		||||
		    <h3 class="section-subheading text-muted">{% trans "" %}</h3>
 | 
			
		||||
		  </div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="row text-center">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,6 @@ class SetPasswordForm(forms.Form):
 | 
			
		|||
        return password2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BillingAddressForm(forms.ModelForm):
 | 
			
		||||
    token = forms.CharField(widget=forms.HiddenInput())
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,6 @@ class StripeUtils(object):
 | 
			
		|||
        )
 | 
			
		||||
        return customer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @handleStripeError
 | 
			
		||||
    def make_charge(self, amount=None, customer=None):
 | 
			
		||||
        amount = int(amount * 100)  # stripe amount unit, in cents
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,51 @@
 | 
			
		|||
from django.test import TestCase
 | 
			
		||||
from .forms import ContactUsForm, BillingAddressForm
 | 
			
		||||
from .forms import ContactUsForm, BillingAddressForm, PasswordResetRequestForm,\
 | 
			
		||||
    SetPasswordForm
 | 
			
		||||
 | 
			
		||||
from model_mommy import mommy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PasswordResetRequestFormTest(TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.user = mommy.make('CustomUser')
 | 
			
		||||
        self.completed_data = {
 | 
			
		||||
            'email': self.user.email,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.incorrect_data = {
 | 
			
		||||
            'email': 'test',
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def test_valid_form(self):
 | 
			
		||||
        form = PasswordResetRequestForm(data=self.completed_data)
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
 | 
			
		||||
    def test_invalid_form(self):
 | 
			
		||||
        form = PasswordResetRequestForm(data=self.incorrect_data)
 | 
			
		||||
        self.assertFalse(form.is_valid())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SetPasswordFormTest(TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        # self.user = mommy.make('CustomUser')
 | 
			
		||||
        self.completed_data = {
 | 
			
		||||
            'new_password1': 'new_password',
 | 
			
		||||
            'new_password2': 'new_password',
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.incorrect_data = {
 | 
			
		||||
            'email': 'test',
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def test_valid_form(self):
 | 
			
		||||
        form = SetPasswordForm(data=self.completed_data)
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
 | 
			
		||||
    def test_invalid_form(self):
 | 
			
		||||
        form = SetPasswordForm(data=self.incorrect_data)
 | 
			
		||||
        self.assertFalse(form.is_valid())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ContactUsFormTest(TestCase):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
from django.test import TestCase
 | 
			
		||||
from django.test import Client
 | 
			
		||||
from django.http.request import HttpRequest
 | 
			
		||||
 | 
			
		||||
from model_mommy import mommy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +30,11 @@ class BaseTestCase(TestCase):
 | 
			
		|||
        self.customer_client = self.get_client(self.customer)
 | 
			
		||||
        self.another_customer_client = self.get_client(self.another_customer)
 | 
			
		||||
 | 
			
		||||
        # Request Object
 | 
			
		||||
        self.request = HttpRequest()
 | 
			
		||||
        self.request.META['SERVER_NAME'] = 'ungleich.com'
 | 
			
		||||
        self.request.META['SERVER_PORT'] = '80'
 | 
			
		||||
 | 
			
		||||
    def get_client(self, user):
 | 
			
		||||
        """
 | 
			
		||||
        Authenticate a user and return the client
 | 
			
		||||
| 
						 | 
				
			
			@ -64,3 +71,14 @@ class BaseTestCase(TestCase):
 | 
			
		|||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def setup_view(self, view, *args, **kwargs):
 | 
			
		||||
        """Mimic as_view() returned callable, but returns view instance.
 | 
			
		||||
 | 
			
		||||
        args and kwargs are the same you would pass to ``reverse()``
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        view.request = self.request
 | 
			
		||||
        view.args = args
 | 
			
		||||
        view.kwargs = kwargs
 | 
			
		||||
        return view
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue