| 
									
										
										
										
											2017-07-06 11:47:12 +03:00
										 |  |  | import datetime | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2017-09-13 02:22:29 +05:30
										 |  |  | import subprocess | 
					
						
							| 
									
										
										
										
											2017-09-01 00:58:30 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 14:31:13 +02:00
										 |  |  | import tempfile | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | from django import forms | 
					
						
							| 
									
										
										
										
											2018-01-08 19:50:42 +01:00
										 |  |  | from django.conf import settings | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | from django.contrib.auth import authenticate | 
					
						
							| 
									
										
										
										
											2017-06-01 20:47:11 +02:00
										 |  |  | from django.utils.translation import ugettext_lazy as _ | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  | from membership.models import CustomUser | 
					
						
							| 
									
										
										
										
											2017-09-13 06:57:15 +05:30
										 |  |  | from utils.hosting_utils import get_all_public_keys | 
					
						
							| 
									
										
										
										
											2018-09-25 02:18:31 +02:00
										 |  |  | from .models import UserHostingKey, GenericProduct | 
					
						
							| 
									
										
										
										
											2016-06-03 00:07:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  | logger = logging.getLogger(__name__) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-06 11:47:12 +03:00
										 |  |  | def generate_ssh_key_name(): | 
					
						
							| 
									
										
										
										
											2018-01-08 19:50:42 +01:00
										 |  |  |     return '{prefix}{date_time_str}'.format( | 
					
						
							|  |  |  |         prefix=settings.DCL_SSH_KEY_NAME_PREFIX, | 
					
						
							|  |  |  |         date_time_str=datetime.datetime.now().strftime('%m%d%y%H%M%S') | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-07-06 11:47:12 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | class HostingUserLoginForm(forms.Form): | 
					
						
							|  |  |  |     email = forms.CharField(widget=forms.EmailInput()) | 
					
						
							|  |  |  |     password = forms.CharField(widget=forms.PasswordInput()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Meta: | 
					
						
							|  |  |  |         fields = ['email', 'password'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def clean(self): | 
					
						
							|  |  |  |         email = self.cleaned_data.get('email') | 
					
						
							|  |  |  |         password = self.cleaned_data.get('password') | 
					
						
							| 
									
										
										
										
											2017-10-14 12:52:18 +02:00
										 |  |  |         if self.errors: | 
					
						
							|  |  |  |             return self.cleaned_data | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  |         is_auth = authenticate(email=email, password=password) | 
					
						
							|  |  |  |         if not is_auth: | 
					
						
							| 
									
										
										
										
											2017-07-29 18:19:10 +05:30
										 |  |  |             raise forms.ValidationError( | 
					
						
							| 
									
										
										
										
											2017-08-03 22:00:41 +05:30
										 |  |  |                 _("Your username and/or password were incorrect.")) | 
					
						
							| 
									
										
										
										
											2017-06-11 05:14:20 +05:30
										 |  |  |         elif is_auth.validated == 0: | 
					
						
							| 
									
										
										
										
											2017-07-29 18:19:10 +05:30
										 |  |  |             raise forms.ValidationError( | 
					
						
							|  |  |  |                 _("Your account is not activated yet.")) | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  |         return self.cleaned_data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def clean_email(self): | 
					
						
							|  |  |  |         email = self.cleaned_data.get('email') | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             CustomUser.objects.get(email=email) | 
					
						
							|  |  |  |             return email | 
					
						
							|  |  |  |         except CustomUser.DoesNotExist: | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |             raise forms.ValidationError(_("User does not exist")) | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 09:13:25 +02:00
										 |  |  | class ProductModelChoiceField(forms.ModelChoiceField): | 
					
						
							|  |  |  |     def label_from_instance(self, obj): | 
					
						
							|  |  |  |         return obj.product_name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-22 08:16:26 +02:00
										 |  |  | class GenericPaymentForm(forms.Form): | 
					
						
							| 
									
										
										
										
											2018-09-26 09:13:25 +02:00
										 |  |  |     product_name = ProductModelChoiceField( | 
					
						
							| 
									
										
										
										
											2018-09-25 02:18:31 +02:00
										 |  |  |         queryset=GenericProduct.objects.all().order_by('product_name'), | 
					
						
							|  |  |  |         empty_label=_("Choose a product"), | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-09-23 12:49:52 +02:00
										 |  |  |     amount = forms.FloatField( | 
					
						
							| 
									
										
										
										
											2018-10-03 08:27:22 +02:00
										 |  |  |         widget=forms.TextInput( | 
					
						
							|  |  |  |             attrs={'placeholder': _('Amount in CHF'), | 
					
						
							| 
									
										
										
										
											2018-10-03 08:38:20 +02:00
										 |  |  |                    'readonly': 'readonly', } | 
					
						
							| 
									
										
										
										
											2018-10-03 08:27:22 +02:00
										 |  |  |         ), | 
					
						
							|  |  |  |         max_value=999999, | 
					
						
							|  |  |  |         min_value=1, | 
					
						
							| 
									
										
										
										
											2018-10-03 08:38:20 +02:00
										 |  |  |         label=_('Amount in CHF') | 
					
						
							| 
									
										
										
										
											2018-10-03 08:27:22 +02:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-09-24 08:32:33 +02:00
										 |  |  |     recurring = forms.BooleanField(required=False, | 
					
						
							| 
									
										
										
										
											2018-10-03 08:27:22 +02:00
										 |  |  |                                    label=_("Recurring monthly"), ) | 
					
						
							| 
									
										
										
										
											2018-09-22 23:51:39 +02:00
										 |  |  |     description = forms.CharField( | 
					
						
							| 
									
										
										
										
											2018-10-03 08:38:20 +02:00
										 |  |  |         widget=forms.Textarea(attrs={'style': "height: 60px;"}), | 
					
						
							| 
									
										
										
										
											2018-09-23 12:49:52 +02:00
										 |  |  |         required=False | 
					
						
							| 
									
										
										
										
											2018-09-22 23:51:39 +02:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-09-22 08:16:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Meta: | 
					
						
							| 
									
										
										
										
											2018-09-26 09:13:25 +02:00
										 |  |  |         model = GenericProduct | 
					
						
							| 
									
										
										
										
											2018-09-25 02:18:31 +02:00
										 |  |  |         fields = ['product_name', 'amount', 'recurring', 'description'] | 
					
						
							| 
									
										
										
										
											2018-09-22 08:16:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 09:14:11 +02:00
										 |  |  |     def clean_amount(self): | 
					
						
							|  |  |  |         amount = self.cleaned_data.get('amount') | 
					
						
							|  |  |  |         if (float(self.cleaned_data.get('product_name').get_actual_price()) != | 
					
						
							|  |  |  |                 amount): | 
					
						
							|  |  |  |             raise forms.ValidationError(_("Amount field does not match")) | 
					
						
							|  |  |  |         return amount | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def clean_recurring(self): | 
					
						
							|  |  |  |         recurring = self.cleaned_data.get('recurring') | 
					
						
							|  |  |  |         if (self.cleaned_data.get('product_name').product_is_subscription != | 
					
						
							|  |  |  |                 (True if recurring else False)): | 
					
						
							|  |  |  |             raise forms.ValidationError(_("Recurring field does not match")) | 
					
						
							|  |  |  |         return recurring | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-22 08:16:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 08:18:45 +02:00
										 |  |  | class ProductPaymentForm(GenericPaymentForm): | 
					
						
							|  |  |  |     def __init__(self, *args, **kwargs): | 
					
						
							| 
									
										
										
										
											2018-10-03 09:38:49 +02:00
										 |  |  |         product_id = kwargs.pop('product_id', None) | 
					
						
							|  |  |  |         if product_id is not None: | 
					
						
							|  |  |  |             self.product = GenericProduct.objects.get(id=product_id) | 
					
						
							|  |  |  |         super(ProductPaymentForm, self).__init__(*args, **kwargs) | 
					
						
							|  |  |  |         self.fields['product_name'] = forms.CharField( | 
					
						
							|  |  |  |             widget=forms.TextInput( | 
					
						
							|  |  |  |                 attrs={'placeholder': _('Product name'), | 
					
						
							| 
									
										
										
										
											2018-10-03 23:17:25 +02:00
										 |  |  |                        'readonly': 'readonly'} | 
					
						
							| 
									
										
										
										
											2018-10-03 09:38:49 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-10-03 08:18:45 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-10-03 22:54:45 +02:00
										 |  |  |         if self.product.product_is_subscription: | 
					
						
							|  |  |  |             self.fields['amount'].label = "{amt} ({payment_type})".format( | 
					
						
							|  |  |  |                 amt=_('Amount in CHF'), | 
					
						
							|  |  |  |                 payment_type=_('Monthly subscription') | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.fields['amount'].label = "{amt} ({payment_type})".format( | 
					
						
							|  |  |  |                 amt=_('Amount in CHF'), | 
					
						
							| 
									
										
										
										
											2018-10-03 23:17:25 +02:00
										 |  |  |                 payment_type=_('One time payment') | 
					
						
							| 
									
										
										
										
											2018-10-03 22:54:45 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-10-03 23:17:25 +02:00
										 |  |  |         self.fields['recurring'].widget = forms.HiddenInput() | 
					
						
							| 
									
										
										
										
											2018-10-05 08:58:10 +02:00
										 |  |  |         self.fields['product_name'].widget.attrs['class'] = 'input-no-border' | 
					
						
							|  |  |  |         self.fields['amount'].widget.attrs['class'] = 'input-no-border' | 
					
						
							|  |  |  |         self.fields['description'].widget.attrs['class'] = 'input-no-border' | 
					
						
							| 
									
										
										
										
											2018-10-03 08:18:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 09:38:49 +02:00
										 |  |  |     def clean_amount(self): | 
					
						
							|  |  |  |         amount = self.cleaned_data.get('amount') | 
					
						
							|  |  |  |         if (self.product is None or | 
					
						
							|  |  |  |                 float(self.product.get_actual_price()) != amount): | 
					
						
							|  |  |  |             raise forms.ValidationError(_("Amount field does not match")) | 
					
						
							|  |  |  |         return amount | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def clean_recurring(self): | 
					
						
							|  |  |  |         recurring = self.cleaned_data.get('recurring') | 
					
						
							|  |  |  |         if (self.product.product_is_subscription != | 
					
						
							|  |  |  |                 (True if recurring else False)): | 
					
						
							|  |  |  |             raise forms.ValidationError(_("Recurring field does not match")) | 
					
						
							|  |  |  |         return recurring | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 08:18:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | class HostingUserSignupForm(forms.ModelForm): | 
					
						
							| 
									
										
										
										
											2017-10-26 03:24:29 +05:30
										 |  |  |     confirm_password = forms.CharField(label=_("Confirm Password"), | 
					
						
							|  |  |  |                                        widget=forms.PasswordInput()) | 
					
						
							|  |  |  |     password = forms.CharField(label=_("Password"), | 
					
						
							|  |  |  |                                widget=forms.PasswordInput()) | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Meta: | 
					
						
							|  |  |  |         model = CustomUser | 
					
						
							|  |  |  |         fields = ['name', 'email', 'password'] | 
					
						
							|  |  |  |         widgets = { | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |             'name': forms.TextInput( | 
					
						
							| 
									
										
										
										
											2017-10-26 03:24:29 +05:30
										 |  |  |                 attrs={'placeholder': _('Enter your name or company name')}), | 
					
						
							| 
									
										
										
										
											2016-04-20 01:03:32 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def clean_confirm_password(self): | 
					
						
							|  |  |  |         password = self.cleaned_data.get('password') | 
					
						
							|  |  |  |         confirm_password = self.cleaned_data.get('confirm_password') | 
					
						
							|  |  |  |         if not confirm_password == password: | 
					
						
							|  |  |  |             raise forms.ValidationError("Passwords don't match") | 
					
						
							|  |  |  |         return confirm_password | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class UserHostingKeyForm(forms.ModelForm): | 
					
						
							| 
									
										
										
										
											2017-06-01 20:47:11 +02:00
										 |  |  |     private_key = forms.CharField(widget=forms.HiddenInput(), required=False) | 
					
						
							| 
									
										
										
										
											2017-07-05 16:57:49 +03:00
										 |  |  |     public_key = forms.CharField(widget=forms.Textarea( | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |         attrs={'class': 'form_public_key', | 
					
						
							|  |  |  |                'placeholder': _('Paste here your public key')}), | 
					
						
							| 
									
										
										
										
											2017-07-05 16:57:49 +03:00
										 |  |  |         required=False, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-06-01 20:47:11 +02:00
										 |  |  |     user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(), | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |                                          required=False, | 
					
						
							|  |  |  |                                          widget=forms.HiddenInput()) | 
					
						
							| 
									
										
										
										
											2017-07-06 11:47:12 +03:00
										 |  |  |     name = forms.CharField(required=False, widget=forms.TextInput( | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |         attrs={'class': 'form_key_name', | 
					
						
							|  |  |  |                'placeholder': _('Give a name to your key')})) | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, *args, **kwargs): | 
					
						
							|  |  |  |         self.request = kwargs.pop("request") | 
					
						
							|  |  |  |         super(UserHostingKeyForm, self).__init__(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2017-07-31 19:43:15 +05:30
										 |  |  |         self.fields['name'].label = _('Key name') | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |     def clean_public_key(self): | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-09-13 14:31:13 +02:00
										 |  |  |         Validates a public ssh key using `ssh-keygen -lf key.pub` | 
					
						
							|  |  |  |         Also checks if a given key already exists in the database and | 
					
						
							|  |  |  |         alerts the user of it. | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |         :return: | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:20:00 +02:00
										 |  |  |         if 'generate' in self.request.POST: | 
					
						
							|  |  |  |             return self.data.get('public_key') | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  |         KEY_ERROR_MESSAGE = _("Please input a proper SSH key") | 
					
						
							| 
									
										
										
										
											2017-09-13 06:27:46 +05:30
										 |  |  |         openssh_pubkey_str = self.data.get('public_key').strip() | 
					
						
							| 
									
										
										
										
											2017-09-13 02:22:29 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 06:57:15 +05:30
										 |  |  |         if openssh_pubkey_str in get_all_public_keys(self.request.user): | 
					
						
							|  |  |  |             key_name = UserHostingKey.objects.filter( | 
					
						
							| 
									
										
										
										
											2017-09-13 07:03:49 +05:30
										 |  |  |                 user_id=self.request.user.id, | 
					
						
							| 
									
										
										
										
											2017-09-13 06:57:15 +05:30
										 |  |  |                 public_key=openssh_pubkey_str).first().name | 
					
						
							|  |  |  |             KEY_EXISTS_MESSAGE = _( | 
					
						
							| 
									
										
										
										
											2017-09-14 00:50:24 +05:30
										 |  |  |                 "This key exists already with the name \"%(name)s\"") % { | 
					
						
							| 
									
										
										
										
											2018-10-03 08:27:22 +02:00
										 |  |  |                                      'name': key_name} | 
					
						
							| 
									
										
										
										
											2017-09-13 06:57:15 +05:30
										 |  |  |             raise forms.ValidationError(KEY_EXISTS_MESSAGE) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 02:22:29 +05:30
										 |  |  |         with tempfile.NamedTemporaryFile(delete=True) as tmp_public_key_file: | 
					
						
							| 
									
										
										
										
											2017-09-13 02:31:19 +05:30
										 |  |  |             tmp_public_key_file.write(openssh_pubkey_str.encode('utf-8')) | 
					
						
							| 
									
										
										
										
											2017-09-13 02:22:29 +05:30
										 |  |  |             tmp_public_key_file.flush() | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-09-13 06:07:12 +05:30
										 |  |  |                 subprocess.check_output( | 
					
						
							| 
									
										
										
										
											2017-09-13 02:22:29 +05:30
										 |  |  |                     ['ssh-keygen', '-lf', tmp_public_key_file.name]) | 
					
						
							|  |  |  |             except subprocess.CalledProcessError as cpe: | 
					
						
							|  |  |  |                 logger.debug( | 
					
						
							| 
									
										
										
										
											2017-09-13 02:33:21 +05:30
										 |  |  |                     "Not a correct ssh format {error}".format(error=str(cpe))) | 
					
						
							| 
									
										
										
										
											2017-09-13 02:22:29 +05:30
										 |  |  |                 raise forms.ValidationError(KEY_ERROR_MESSAGE) | 
					
						
							| 
									
										
										
										
											2017-09-07 00:31:09 +02:00
										 |  |  |         return openssh_pubkey_str | 
					
						
							| 
									
										
										
										
											2017-08-31 12:53:00 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  |     def clean_name(self): | 
					
						
							| 
									
										
										
										
											2017-06-01 20:47:11 +02:00
										 |  |  |         return self.data.get('name') | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def clean_user(self): | 
					
						
							|  |  |  |         return self.request.user | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def clean(self): | 
					
						
							|  |  |  |         cleaned_data = self.cleaned_data | 
					
						
							| 
									
										
										
										
											2017-08-03 15:07:36 +02:00
										 |  |  |         if 'generate' in self.request.POST: | 
					
						
							| 
									
										
										
										
											2017-07-06 11:47:12 +03:00
										 |  |  |             self.cleaned_data['name'] = generate_ssh_key_name() | 
					
						
							| 
									
										
										
										
											2017-05-03 23:19:32 -05:00
										 |  |  |             private_key, public_key = UserHostingKey.generate_keys() | 
					
						
							|  |  |  |             cleaned_data.update({ | 
					
						
							|  |  |  |                 'private_key': private_key, | 
					
						
							|  |  |  |                 'public_key': public_key | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return cleaned_data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Meta: | 
					
						
							|  |  |  |         model = UserHostingKey | 
					
						
							| 
									
										
										
										
											2017-06-01 20:47:11 +02:00
										 |  |  |         fields = ['user', 'name', 'public_key'] |