Merge pull request #81 from levivm/develop
SSH Key, notifications and VM status.
This commit is contained in:
		
				commit
				
					
						c03ff34aec
					
				
			
		
					 22 changed files with 392 additions and 22 deletions
				
			
		| 
						 | 
					@ -54,6 +54,7 @@ INSTALLED_APPS = (
 | 
				
			||||||
    'django.contrib.sites',
 | 
					    'django.contrib.sites',
 | 
				
			||||||
    'easy_thumbnails',
 | 
					    'easy_thumbnails',
 | 
				
			||||||
    'utils',
 | 
					    'utils',
 | 
				
			||||||
 | 
					    'stored_messages',
 | 
				
			||||||
    'mptt',
 | 
					    'mptt',
 | 
				
			||||||
    'parler',
 | 
					    'parler',
 | 
				
			||||||
    'taggit',
 | 
					    'taggit',
 | 
				
			||||||
| 
						 | 
					@ -132,6 +133,7 @@ TEMPLATES = [
 | 
				
			||||||
        'DIRS': [os.path.join(PROJECT_DIR, 'cms_templates/'),
 | 
					        'DIRS': [os.path.join(PROJECT_DIR, 'cms_templates/'),
 | 
				
			||||||
                 os.path.join(PROJECT_DIR, 'cms_templates/djangocms_blog/'),
 | 
					                 os.path.join(PROJECT_DIR, 'cms_templates/djangocms_blog/'),
 | 
				
			||||||
                 os.path.join(PROJECT_DIR, 'membership'),
 | 
					                 os.path.join(PROJECT_DIR, 'membership'),
 | 
				
			||||||
 | 
					                 os.path.join(PROJECT_DIR, 'hosting/templates/'),
 | 
				
			||||||
                 os.path.join(PROJECT_DIR, 'ungleich/templates/djangocms_blog/'),
 | 
					                 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/cms/ungleichch'),
 | 
				
			||||||
                 os.path.join(PROJECT_DIR, 'ungleich/templates/ungleich')
 | 
					                 os.path.join(PROJECT_DIR, 'ungleich/templates/ungleich')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,32 @@
 | 
				
			||||||
from django.contrib import admin
 | 
					from django.contrib import admin
 | 
				
			||||||
from .models import VirtualMachineType
 | 
					
 | 
				
			||||||
 | 
					from utils.mailer import BaseEmail
 | 
				
			||||||
 | 
					from .models import VirtualMachineType, VirtualMachinePlan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VirtualMachinePlanAdmin(admin.ModelAdmin):
 | 
				
			||||||
 | 
					    list_display = ('name', 'id', 'email')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def email(self, obj):
 | 
				
			||||||
 | 
					        return obj.hosting_orders.latest('id').customer.user.email
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save_model(self, request, obj, form, change):
 | 
				
			||||||
 | 
					        email = self.email(obj)
 | 
				
			||||||
 | 
					        if 'status' in form.changed_data and obj.status == VirtualMachinePlan.ONLINE_STATUS:
 | 
				
			||||||
 | 
					            context = {
 | 
				
			||||||
 | 
					                'vm': obj
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            email_data = {
 | 
				
			||||||
 | 
					                'subject': 'Your VM has been activated',
 | 
				
			||||||
 | 
					                'to': email,
 | 
				
			||||||
 | 
					                'context': context,
 | 
				
			||||||
 | 
					                'template_name': 'vm_activated',
 | 
				
			||||||
 | 
					                'template_path': 'emails/'
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            email = BaseEmail(**email_data)
 | 
				
			||||||
 | 
					            email.send()
 | 
				
			||||||
 | 
					        obj.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
admin.site.register(VirtualMachineType)
 | 
					admin.site.register(VirtualMachineType)
 | 
				
			||||||
 | 
					admin.site.register(VirtualMachinePlan, VirtualMachinePlanAdmin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								hosting/migrations/0019_virtualmachineplan_status.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								hosting/migrations/0019_virtualmachineplan_status.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2016-05-26 02:57
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('hosting', '0018_virtualmachineplan_public_key'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AddField(
 | 
				
			||||||
 | 
					            model_name='virtualmachineplan',
 | 
				
			||||||
 | 
					            name='status',
 | 
				
			||||||
 | 
					            field=models.CharField(choices=[('pending', 'Pending for activation'), ('online', 'Online')], default='online', max_length=20),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
							
								
								
									
										20
									
								
								hosting/migrations/0020_auto_20160526_0258.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								hosting/migrations/0020_auto_20160526_0258.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2016-05-26 02:58
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('hosting', '0019_virtualmachineplan_status'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AlterField(
 | 
				
			||||||
 | 
					            model_name='virtualmachineplan',
 | 
				
			||||||
 | 
					            name='status',
 | 
				
			||||||
 | 
					            field=models.CharField(choices=[('pending', 'Pending for activation'), ('online', 'Online')], default='pending', max_length=20),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
							
								
								
									
										20
									
								
								hosting/migrations/0021_auto_20160526_0445.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								hosting/migrations/0021_auto_20160526_0445.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2016-05-26 04:45
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('hosting', '0020_auto_20160526_0258'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AlterField(
 | 
				
			||||||
 | 
					            model_name='virtualmachineplan',
 | 
				
			||||||
 | 
					            name='status',
 | 
				
			||||||
 | 
					            field=models.CharField(choices=[('pending', 'Pending for activation'), ('online', 'Online'), ('canceled', 'Canceled')], default='pending', max_length=20),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					@ -3,12 +3,13 @@ import os
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
from django.utils.functional import cached_property
 | 
					from django.utils.functional import cached_property
 | 
				
			||||||
from membership.models import StripeCustomer
 | 
					
 | 
				
			||||||
from utils.models import BillingAddress
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from Crypto.PublicKey import RSA
 | 
					from Crypto.PublicKey import RSA
 | 
				
			||||||
 | 
					from stored_messages.settings import stored_messages_settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from membership.models import StripeCustomer
 | 
				
			||||||
 | 
					from utils.models import BillingAddress
 | 
				
			||||||
from .managers import VMPlansManager
 | 
					from .managers import VMPlansManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,12 +82,24 @@ class VirtualMachineType(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VirtualMachinePlan(models.Model):
 | 
					class VirtualMachinePlan(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PENDING_STATUS = 'pending'
 | 
				
			||||||
 | 
					    ONLINE_STATUS = 'online'
 | 
				
			||||||
 | 
					    CANCELED_STATUS = 'canceled'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VM_STATUS_CHOICES = (
 | 
				
			||||||
 | 
					        (PENDING_STATUS, 'Pending for activation'),
 | 
				
			||||||
 | 
					        (ONLINE_STATUS, 'Online'),
 | 
				
			||||||
 | 
					        (CANCELED_STATUS, 'Canceled')
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cores = models.IntegerField()
 | 
					    cores = models.IntegerField()
 | 
				
			||||||
    memory = models.IntegerField()
 | 
					    memory = models.IntegerField()
 | 
				
			||||||
    disk_size = models.IntegerField()
 | 
					    disk_size = models.IntegerField()
 | 
				
			||||||
    vm_type = models.ForeignKey(VirtualMachineType)
 | 
					    vm_type = models.ForeignKey(VirtualMachineType)
 | 
				
			||||||
    price = models.FloatField()
 | 
					    price = models.FloatField()
 | 
				
			||||||
    public_key = models.TextField()
 | 
					    public_key = models.TextField()
 | 
				
			||||||
 | 
					    status = models.CharField(max_length=20, choices=VM_STATUS_CHOICES, default=PENDING_STATUS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    objects = VMPlansManager()
 | 
					    objects = VMPlansManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,11 +110,22 @@ class VirtualMachinePlan(models.Model):
 | 
				
			||||||
    def hosting_company_name(self):
 | 
					    def hosting_company_name(self):
 | 
				
			||||||
        return self.vm_type.get_hosting_company_display()
 | 
					        return self.vm_type.get_hosting_company_display()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @cached_property
 | 
				
			||||||
 | 
					    def location(self):
 | 
				
			||||||
 | 
					        return self.vm_type.get_location_display()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @cached_property
 | 
					    @cached_property
 | 
				
			||||||
    def name(self):
 | 
					    def name(self):
 | 
				
			||||||
        name = 'vm-%s' % self.id
 | 
					        name = 'vm-%s' % self.id
 | 
				
			||||||
        return name
 | 
					        return name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @cached_property
 | 
				
			||||||
 | 
					    def notifications(self):
 | 
				
			||||||
 | 
					        stripe_customer = StripeCustomer.objects.get(hostingorder__vm_plan=self)
 | 
				
			||||||
 | 
					        backend = stored_messages_settings.STORAGE_BACKEND()
 | 
				
			||||||
 | 
					        messages = backend.inbox_list(stripe_customer.user)
 | 
				
			||||||
 | 
					        return messages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def create(cls, data, user):
 | 
					    def create(cls, data, user):
 | 
				
			||||||
        instance = cls.objects.create(**data)
 | 
					        instance = cls.objects.create(**data)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 741 B  | 
							
								
								
									
										12
									
								
								hosting/templates/emails/new_booked_vm.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								hosting/templates/emails/new_booked_vm.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<title></title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NEW VM BOOKED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										12
									
								
								hosting/templates/emails/new_booked_vm.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								hosting/templates/emails/new_booked_vm.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<title></title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NEW VM BOOKED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										13
									
								
								hosting/templates/emails/vm_activated.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								hosting/templates/emails/vm_activated.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load staticfiles bootstrap3%}
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<title></title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 You virtual machine {{vm.name}} has been activated. You can manage your vm on this <a href="{{request.HOS}}{% url 'hosting:virtual_machines' vm.id %}"> link </a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										15
									
								
								hosting/templates/emails/vm_activated.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								hosting/templates/emails/vm_activated.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load staticfiles bootstrap3%}
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<title></title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 You virtual machine {{vm.name}} has been activated. You can manage your vm in this <a href="{% url 'hosting:virtual_machines' vm.id %}"> link </a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,11 @@
 | 
				
			||||||
                                <i class="fa fa-credit-card"></i> My Orders
 | 
					                                <i class="fa fa-credit-card"></i> My Orders
 | 
				
			||||||
                            </a>
 | 
					                            </a>
 | 
				
			||||||
                        </li>
 | 
					                        </li>
 | 
				
			||||||
 | 
					                        <li>
 | 
				
			||||||
 | 
					                            <a href="{% url 'hosting:notifications' %}">
 | 
				
			||||||
 | 
					                                <i class="fa fa-bell"></i> Notifications
 | 
				
			||||||
 | 
					                            </a>
 | 
				
			||||||
 | 
					                        </li>
 | 
				
			||||||
                        <li class="dropdown">
 | 
					                        <li class="dropdown">
 | 
				
			||||||
                          <a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
 | 
					                          <a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
 | 
				
			||||||
                            <i class="glyphicon glyphicon-user"></i> {{request.user.name}} <span class="caret"></span></a>
 | 
					                            <i class="glyphicon glyphicon-user"></i> {{request.user.name}} <span class="caret"></span></a>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@
 | 
				
			||||||
                <ul class="pricing {% cycle 'p-red' 'p-black' 'p-red' 'p-yel' %}">
 | 
					                <ul class="pricing {% cycle 'p-red' 'p-black' 'p-red' 'p-yel' %}">
 | 
				
			||||||
                  <li class="type">
 | 
					                  <li class="type">
 | 
				
			||||||
                    <!-- <img src="http://bread.pp.ua/n/settings_g.svg" alt=""> -->
 | 
					                    <!-- <img src="http://bread.pp.ua/n/settings_g.svg" alt=""> -->
 | 
				
			||||||
                    <h3 >{{vm.hosting_company_name}}</h3>
 | 
					                    <h3 >{{vm.location_code}}</h3>
 | 
				
			||||||
                    <br/>
 | 
					                    <br/>
 | 
				
			||||||
                    <img class="img-responsive" src="{{ STATIC_URL }}hosting/img/{{vm.location_code}}_flag.png" alt="">
 | 
					                    <img class="img-responsive" src="{{ STATIC_URL }}hosting/img/{{vm.location_code}}_flag.png" alt="">
 | 
				
			||||||
                   
 | 
					                   
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										90
									
								
								hosting/templates/hosting/notifications.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								hosting/templates/hosting/notifications.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,90 @@
 | 
				
			||||||
 | 
					{% extends "hosting/base_short.html" %}
 | 
				
			||||||
 | 
					{% load staticfiles bootstrap3 %}
 | 
				
			||||||
 | 
					{% block content %} 
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
						<div class="container virtual-machine-container dashboard-container ">
 | 
				
			||||||
 | 
							<div class="row">
 | 
				
			||||||
 | 
								<div class="col-md-9 col-md-offset-2">
 | 
				
			||||||
 | 
									 <div  class="col-sm-12">
 | 
				
			||||||
 | 
									        <h3><i class="fa fa-bell" aria-hidden="true"></i> Notifications</h3>
 | 
				
			||||||
 | 
									        <hr/>
 | 
				
			||||||
 | 
									        <div class="col-md-3"> <!-- required for floating -->
 | 
				
			||||||
 | 
									          <!-- Nav tabs -->
 | 
				
			||||||
 | 
									          <ul class="nav nav-tabs tabs-left sideways">
 | 
				
			||||||
 | 
									            <li  class="active">
 | 
				
			||||||
 | 
									            	<a href="#unread-v" data-toggle="tab">
 | 
				
			||||||
 | 
									            		Unread  <span class="badge">{{unread_notifications|length}}</span>
 | 
				
			||||||
 | 
									            	</a>
 | 
				
			||||||
 | 
									            </li>
 | 
				
			||||||
 | 
									            <li>
 | 
				
			||||||
 | 
									            	<a href="#all-v" data-toggle="tab">
 | 
				
			||||||
 | 
									            		 All
 | 
				
			||||||
 | 
									            	</a>
 | 
				
			||||||
 | 
									            </li>
 | 
				
			||||||
 | 
									          </ul>
 | 
				
			||||||
 | 
									        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									        <div class="col-md-9">
 | 
				
			||||||
 | 
									          <!-- Tab panes -->
 | 
				
			||||||
 | 
									          <div class="tab-content">
 | 
				
			||||||
 | 
									            <div class="tab-pane active" id="unread-v">
 | 
				
			||||||
 | 
									            	<div class="row">
 | 
				
			||||||
 | 
														<div class="col-md-12">
 | 
				
			||||||
 | 
														<h3>Unread notifications</h3>
 | 
				
			||||||
 | 
														<hr>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
									            	</div>
 | 
				
			||||||
 | 
													<div class="row">
 | 
				
			||||||
 | 
													  <div class="col-md-12"> 
 | 
				
			||||||
 | 
															{% for notification in unread_notifications %}
 | 
				
			||||||
 | 
																<form method="POST" action="{% url 'hosting:read_notification' notification.id %}">
 | 
				
			||||||
 | 
																	{% csrf_token %} 
 | 
				
			||||||
 | 
																	<span>{{notification}} -</span>
 | 
				
			||||||
 | 
																	<button type="submit" class="btn btn-link">Mark as read</button>
 | 
				
			||||||
 | 
												                	<span  class="pull-right" style="font-size: 11px;color: #999;">{{notification.date}}</span>
 | 
				
			||||||
 | 
																</form>
 | 
				
			||||||
 | 
																<hr/>
 | 
				
			||||||
 | 
															{% endfor %}
 | 
				
			||||||
 | 
													  </div><!--/col-12-->
 | 
				
			||||||
 | 
													</div><!--/row-->
 | 
				
			||||||
 | 
									            </div>
 | 
				
			||||||
 | 
									            <div class="tab-pane" id="all-v">
 | 
				
			||||||
 | 
									            	<div class="row">
 | 
				
			||||||
 | 
														<div class="col-md-12">
 | 
				
			||||||
 | 
														<h3>All notifications</h3>
 | 
				
			||||||
 | 
														<hr>
 | 
				
			||||||
 | 
														{% for notification in all_notifications %}
 | 
				
			||||||
 | 
															<span>{{notification.message}} </span>
 | 
				
			||||||
 | 
															<span class="pull-right" style="font-size: 11px;color: #999;">{{notification.message.date}}</span>
 | 
				
			||||||
 | 
															<hr/>
 | 
				
			||||||
 | 
														{% endfor %}
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
									            	</div>
 | 
				
			||||||
 | 
													<div class="row">
 | 
				
			||||||
 | 
													  <div class="col-md-12"> 
 | 
				
			||||||
 | 
													  </div><!--/col-12-->
 | 
				
			||||||
 | 
													</div><!--/row-->
 | 
				
			||||||
 | 
									            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									          </div>
 | 
				
			||||||
 | 
									        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									        <div class="clearfix"></div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    </div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{%endblock%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,12 +122,16 @@
 | 
				
			||||||
								</div><!--/row-->
 | 
													</div><!--/row-->
 | 
				
			||||||
				            </div>
 | 
									            </div>
 | 
				
			||||||
				            <div class="tab-pane" id="status-v">
 | 
									            <div class="tab-pane" id="status-v">
 | 
				
			||||||
 | 
					 | 
				
			||||||
				            	<div class="row ">
 | 
									            	<div class="row ">
 | 
				
			||||||
									<div class="col-md-12 inline-headers">
 | 
														<div class="col-md-12 inline-headers">
 | 
				
			||||||
										<h3>Current status</h3>
 | 
															<h3>Current status</h3>
 | 
				
			||||||
										<span class="h3 pull-right label label-success"><strong>Online</strong></span> 
 | 
															{% if virtual_machine.status == 'pending' %}
 | 
				
			||||||
										<hr>
 | 
																<span class="h3 pull-right label label-warning"><strong>{{virtual_machine.get_status_display}}</strong></span>
 | 
				
			||||||
 | 
															{% elif  virtual_machine.status == 'online' %}
 | 
				
			||||||
 | 
																<span class="h3 pull-right label label-success"><strong>{{virtual_machine.get_status_display}}</strong></span>
 | 
				
			||||||
 | 
															{% else %}
 | 
				
			||||||
 | 
																<span class="h3 pull-right label label-error"><strong>{{virtual_machine.get_status_display}}</strong></span>
 | 
				
			||||||
 | 
															{% endif %}   
 | 
				
			||||||
									</div>
 | 
														</div>
 | 
				
			||||||
				            	</div>
 | 
									            	</div>
 | 
				
			||||||
				            </div>
 | 
									            </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@
 | 
				
			||||||
				<thead> 
 | 
									<thead> 
 | 
				
			||||||
				<tr> 
 | 
									<tr> 
 | 
				
			||||||
					<th>ID</th>
 | 
										<th>ID</th>
 | 
				
			||||||
					<th>Type</th>
 | 
										<th>Location</th>
 | 
				
			||||||
					<th>Amount</th>
 | 
										<th>Amount</th>
 | 
				
			||||||
					<th></th>
 | 
										<th></th>
 | 
				
			||||||
				</tr>
 | 
									</tr>
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
					{% for vm in vms %}
 | 
										{% for vm in vms %}
 | 
				
			||||||
					<tr> 
 | 
										<tr> 
 | 
				
			||||||
						<td scope="row">{{vm.name}}</td> 
 | 
											<td scope="row">{{vm.name}}</td> 
 | 
				
			||||||
						<td>{{vm.hosting_company_name}}</td> 
 | 
											<td>{{vm.location}}</td> 
 | 
				
			||||||
						<td>{{vm.price}} CHF</td> 
 | 
											<td>{{vm.price}} CHF</td> 
 | 
				
			||||||
						<td>
 | 
											<td>
 | 
				
			||||||
							<button type="button" class="btn btn-default"><a href="{% url 'hosting:virtual_machines' vm.id %}">View Detail</a></button>
 | 
												<button type="button" class="btn btn-default"><a href="{% url 'hosting:virtual_machines' vm.id %}">View Detail</a></button>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,10 @@
 | 
				
			||||||
from django.conf.urls import url
 | 
					from django.conf.urls import url
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .views import DjangoHostingView, RailsHostingView, PaymentVMView, \
 | 
					from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
 | 
				
			||||||
    NodeJSHostingView, LoginView, SignupView, IndexView, \
 | 
					    NodeJSHostingView, LoginView, SignupView, IndexView, \
 | 
				
			||||||
    OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
 | 
					    OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
 | 
				
			||||||
    VirtualMachineDetailView, GenerateVMSSHKeysView, OrdersHostingDeleteView
 | 
					    VirtualMachineDetailView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \
 | 
				
			||||||
 | 
					    MarkAsReadNotificationView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = [
 | 
					urlpatterns = [
 | 
				
			||||||
    # url(r'pricing/?$', VMPricingView.as_view(), name='pricing'),
 | 
					    # url(r'pricing/?$', VMPricingView.as_view(), name='pricing'),
 | 
				
			||||||
| 
						 | 
					@ -20,6 +21,9 @@ urlpatterns = [
 | 
				
			||||||
        name='virtual_machines'),
 | 
					        name='virtual_machines'),
 | 
				
			||||||
    url(r'my-virtual-machines/(?P<pk>\d+)/key/?$', GenerateVMSSHKeysView.as_view(),
 | 
					    url(r'my-virtual-machines/(?P<pk>\d+)/key/?$', GenerateVMSSHKeysView.as_view(),
 | 
				
			||||||
        name='virtual_machine_key'),
 | 
					        name='virtual_machine_key'),
 | 
				
			||||||
 | 
					    url(r'^notifications/$', NotificationsView.as_view(), name='notifications'),
 | 
				
			||||||
 | 
					    url(r'^notifications/(?P<pk>\d+)/?$', MarkAsReadNotificationView.as_view(),
 | 
				
			||||||
 | 
					        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'^logout/?$', 'django.contrib.auth.views.logout',
 | 
					    url(r'^logout/?$', 'django.contrib.auth.views.logout',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,17 +2,22 @@
 | 
				
			||||||
from django.shortcuts import get_object_or_404, render,render_to_response
 | 
					from django.shortcuts import get_object_or_404, render,render_to_response
 | 
				
			||||||
from django.core.urlresolvers import reverse_lazy, reverse
 | 
					from django.core.urlresolvers import reverse_lazy, reverse
 | 
				
			||||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
					from django.contrib.auth.mixins import LoginRequiredMixin
 | 
				
			||||||
 | 
					from django.views.generic import View, CreateView, FormView, ListView, DetailView,\
 | 
				
			||||||
from django.views.generic import View, CreateView, FormView, ListView, DetailView, UpdateView, DeleteView
 | 
					    DeleteView, TemplateView, UpdateView
 | 
				
			||||||
from django.http import HttpResponseRedirect, HttpResponse
 | 
					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
 | 
				
			||||||
from django.contrib import messages
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from stored_messages.settings import stored_messages_settings
 | 
				
			||||||
 | 
					from stored_messages.models import Message
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
from utils.models import BillingAddress
 | 
					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
 | 
				
			||||||
from .mixins import ProcessVMSelectionMixin
 | 
					from .mixins import ProcessVMSelectionMixin
 | 
				
			||||||
| 
						 | 
					@ -145,6 +150,34 @@ class SignupView(CreateView):
 | 
				
			||||||
        return HttpResponseRedirect(self.get_success_url())
 | 
					        return HttpResponseRedirect(self.get_success_url())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotificationsView(TemplateView):
 | 
				
			||||||
 | 
					    template_name = 'hosting/notifications.html'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_context_data(self, **kwargs):
 | 
				
			||||||
 | 
					        context = super(NotificationsView, self).get_context_data(**kwargs)
 | 
				
			||||||
 | 
					        backend = stored_messages_settings.STORAGE_BACKEND()
 | 
				
			||||||
 | 
					        unread_notifications = backend.inbox_list(self.request.user)
 | 
				
			||||||
 | 
					        read_notifications = backend.archive_list(self.request.user)
 | 
				
			||||||
 | 
					        context.update({
 | 
				
			||||||
 | 
					            'unread_notifications': unread_notifications,
 | 
				
			||||||
 | 
					            'all_notifications': read_notifications + unread_notifications
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MarkAsReadNotificationView(LoginRequiredMixin, UpdateView):
 | 
				
			||||||
 | 
					    model = Message
 | 
				
			||||||
 | 
					    success_url = reverse_lazy('hosting:notifications')
 | 
				
			||||||
 | 
					    fields = '__all__'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def post(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        message = self.get_object()
 | 
				
			||||||
 | 
					        backend = stored_messages_settings.STORAGE_BACKEND()
 | 
				
			||||||
 | 
					        backend.archive_store([self.request.user], message)
 | 
				
			||||||
 | 
					        mark_read(self.request.user, message)
 | 
				
			||||||
 | 
					        return HttpResponseRedirect(reverse('hosting:notifications'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GenerateVMSSHKeysView(LoginRequiredMixin, DetailView):
 | 
					class GenerateVMSSHKeysView(LoginRequiredMixin, DetailView):
 | 
				
			||||||
    model = VirtualMachinePlan
 | 
					    model = VirtualMachinePlan
 | 
				
			||||||
    template_name = 'hosting/virtual_machine_key.html'
 | 
					    template_name = 'hosting/virtual_machine_key.html'
 | 
				
			||||||
| 
						 | 
					@ -174,6 +207,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
 | 
				
			||||||
        context.update({
 | 
					        context.update({
 | 
				
			||||||
            'stripe_key': settings.STRIPE_API_PUBLIC_KEY
 | 
					            'stripe_key': settings.STRIPE_API_PUBLIC_KEY
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def post(self, request, *args, **kwargs):
 | 
					    def post(self, request, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -199,7 +233,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
 | 
				
			||||||
            customer = StripeCustomer.get_or_create(email=self.request.user.email,
 | 
					            customer = StripeCustomer.get_or_create(email=self.request.user.email,
 | 
				
			||||||
                                                    token=token)
 | 
					                                                    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(self.get_context_data(form=form))
 | 
					                return self.render_to_response(self.get_context_data(form=form))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Create Virtual Machine Plan
 | 
					            # Create Virtual Machine Plan
 | 
				
			||||||
| 
						 | 
					@ -233,6 +267,18 @@ class PaymentVMView(LoginRequiredMixin, FormView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # If the Stripe payment was successed, set order status approved
 | 
					            # If the Stripe payment was successed, set order status approved
 | 
				
			||||||
            order.set_approved()
 | 
					            order.set_approved()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Send notification to ungleich as soon as VM has been booked
 | 
				
			||||||
 | 
					            # TODO send email using celery
 | 
				
			||||||
 | 
					            email_data = {
 | 
				
			||||||
 | 
					                'subject': 'New VM request',
 | 
				
			||||||
 | 
					                'to': 'info@ungleich.ch',
 | 
				
			||||||
 | 
					                'template_name': 'new_booked_vm',
 | 
				
			||||||
 | 
					                'template_path': 'emails/'
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            email = BaseEmail(**email_data)
 | 
				
			||||||
 | 
					            email.send()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            request.session.update({
 | 
					            request.session.update({
 | 
				
			||||||
                'charge': charge,
 | 
					                'charge': charge,
 | 
				
			||||||
                'order': order.id,
 | 
					                'order': order.id,
 | 
				
			||||||
| 
						 | 
					@ -265,10 +311,11 @@ class OrdersHostingListView(LoginRequiredMixin, ListView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OrdersHostingDeleteView(LoginRequiredMixin, DeleteView):
 | 
					class OrdersHostingDeleteView(LoginRequiredMixin, DeleteView):
 | 
				
			||||||
    login_url=reverse_lazy('hosting:login')
 | 
					    login_url = reverse_lazy('hosting:login')
 | 
				
			||||||
    success_url = reverse_lazy('hosting:orders')
 | 
					    success_url = reverse_lazy('hosting:orders')
 | 
				
			||||||
    model = HostingOrder
 | 
					    model = HostingOrder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
 | 
					class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
 | 
				
			||||||
    template_name = "hosting/virtual_machines.html"
 | 
					    template_name = "hosting/virtual_machines.html"
 | 
				
			||||||
    login_url = reverse_lazy('hosting:login')
 | 
					    login_url = reverse_lazy('hosting:login')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										31
									
								
								membership/migrations/0006_auto_20160526_0445.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								membership/migrations/0006_auto_20160526_0445.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2016-05-26 04:45
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('auth', '0007_alter_validators_add_error_messages'),
 | 
				
			||||||
 | 
					        ('membership', '0005_customuser_is_admin'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AddField(
 | 
				
			||||||
 | 
					            model_name='customuser',
 | 
				
			||||||
 | 
					            name='groups',
 | 
				
			||||||
 | 
					            field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        migrations.AddField(
 | 
				
			||||||
 | 
					            model_name='customuser',
 | 
				
			||||||
 | 
					            name='is_superuser',
 | 
				
			||||||
 | 
					            field=models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        migrations.AddField(
 | 
				
			||||||
 | 
					            model_name='customuser',
 | 
				
			||||||
 | 
					            name='user_permissions',
 | 
				
			||||||
 | 
					            field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser
 | 
					from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, PermissionsMixin
 | 
				
			||||||
from django.contrib.auth.hashers import make_password
 | 
					from django.contrib.auth.hashers import make_password
 | 
				
			||||||
from django.core.validators import RegexValidator
 | 
					from django.core.validators import RegexValidator
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ class MyUserManager(BaseUserManager):
 | 
				
			||||||
        return user
 | 
					        return user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CustomUser(AbstractBaseUser):
 | 
					class CustomUser(AbstractBaseUser, PermissionsMixin):
 | 
				
			||||||
    VALIDATED_CHOICES = ((0, 'Not validated'), (1, 'Validated'))
 | 
					    VALIDATED_CHOICES = ((0, 'Not validated'), (1, 'Validated'))
 | 
				
			||||||
    site = models.ForeignKey(Site, default=1)
 | 
					    site = models.ForeignKey(Site, default=1)
 | 
				
			||||||
    name = models.CharField(max_length=50)
 | 
					    name = models.CharField(max_length=50)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ easy_thumbnails
 | 
				
			||||||
django-polymorphic
 | 
					django-polymorphic
 | 
				
			||||||
model-mommy
 | 
					model-mommy
 | 
				
			||||||
pycryptodome
 | 
					pycryptodome
 | 
				
			||||||
 | 
					django-stored-messages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#PLUGINS
 | 
					#PLUGINS
 | 
				
			||||||
djangocms_flash
 | 
					djangocms_flash
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,32 @@
 | 
				
			||||||
import six
 | 
					import six
 | 
				
			||||||
from django.core.mail import send_mail
 | 
					from django.core.mail import send_mail
 | 
				
			||||||
 | 
					from django.core.mail import EmailMultiAlternatives
 | 
				
			||||||
 | 
					from django.template.loader import render_to_string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BaseEmail(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        self.to = kwargs.get('to')
 | 
				
			||||||
 | 
					        self.template_name = kwargs.get('template_name')
 | 
				
			||||||
 | 
					        self.template_path = kwargs.get('template_path')
 | 
				
			||||||
 | 
					        self.subject = kwargs.get('subject')
 | 
				
			||||||
 | 
					        self.context = kwargs.get('context', {})
 | 
				
			||||||
 | 
					        self.template_full_path = '%s%s' % (self.template_path, self.template_name)
 | 
				
			||||||
 | 
					        text_content = render_to_string('%s.txt' % self.template_full_path, self.context)
 | 
				
			||||||
 | 
					        html_content = render_to_string('%s.html' % self.template_full_path, self.context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.email = EmailMultiAlternatives(self.subject, text_content)
 | 
				
			||||||
 | 
					        self.email.attach_alternative(html_content, "text/html")
 | 
				
			||||||
 | 
					        self.email.to = ['info@digitalglarus.ch']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def send(self):
 | 
				
			||||||
 | 
					        self.email.send()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BaseMailer(object):
 | 
					class BaseMailer(object):
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        self._slug = None
 | 
					        self._slug = None
 | 
				
			||||||
| 
						 | 
					@ -50,3 +73,4 @@ class DigitalGlarusRegistrationMailer(BaseMailer):
 | 
				
			||||||
        self.registration = self.message
 | 
					        self.registration = self.message
 | 
				
			||||||
        self._message = self._message.format(slug=self._slug)
 | 
					        self._message = self._message.format(slug=self._slug)
 | 
				
			||||||
        super().__init__()
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue