Merge branch 'master' into task/3713/clean_up_css
This commit is contained in:
		
				commit
				
					
						4b752f31ab
					
				
			
		
					 17 changed files with 359 additions and 20 deletions
				
			
		| 
						 | 
					@ -4,7 +4,7 @@ python:
 | 
				
			||||||
#   - "3.6"
 | 
					#   - "3.6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
env:
 | 
					env:
 | 
				
			||||||
    - DJANGO_SECRET_KEY=0 OPENNEBULA_USERNAME='test' OPENNEBULA_PASSWORD='test' OPENNEBULA_PROTOCOL='http' OPENNEBULA_DOMAIN='test_domain' OPENNEBULA_PORT='2633' OPENNEBULA_ENDPOINT='/RPC2' DCL_TEXT='Data Center Light' CELERY_MAX_RETRIES=0
 | 
					    - DJANGO_SECRET_KEY=0 OPENNEBULA_USERNAME='test' OPENNEBULA_PASSWORD='test' OPENNEBULA_PROTOCOL='http' OPENNEBULA_DOMAIN='test_domain' OPENNEBULA_PORT='2633' OPENNEBULA_ENDPOINT='/RPC2' DCL_TEXT='Data Center Light' CELERY_MAX_RETRIES=0 UNGLEICH_SITE_CONFIGS='{"localhost":{"MULTISITE_CMS_URL":"dynamicweb.urls"}}'
 | 
				
			||||||
# install dependencies
 | 
					# install dependencies
 | 
				
			||||||
install: "pip install -r requirements.txt"
 | 
					install: "pip install -r requirements.txt"
 | 
				
			||||||
script:
 | 
					script:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,8 @@
 | 
				
			||||||
Next:
 | 
					1.4: 2018-02-22
 | 
				
			||||||
 | 
					    * #4104: [cms, nuglarus] Multisite and access control of cms pages per user
 | 
				
			||||||
 | 
					1.3.3: 2018-02-21
 | 
				
			||||||
 | 
					    * Add ALLOWED_HOST nüglarus.ch IDN
 | 
				
			||||||
 | 
					    * #4105: [cms] Add cms footer plugin
 | 
				
			||||||
    * #4049: [blog] Replace header background image
 | 
					    * #4049: [blog] Replace header background image
 | 
				
			||||||
    * #3670: [hosting] Shorten ssh key name
 | 
					    * #3670: [hosting] Shorten ssh key name
 | 
				
			||||||
    * #4046: [hosting] Add sdd_size, hdd_size to VirtualMachineSerializer (No visual change)
 | 
					    * #4046: [hosting] Add sdd_size, hdd_size to VirtualMachineSerializer (No visual change)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ Copyright 2015 ungleich.
 | 
				
			||||||
# -*- coding: utf-8 -*-
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 | 
					# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +55,8 @@ PROJECT_DIR = os.path.abspath(
 | 
				
			||||||
# load .env file
 | 
					# load .env file
 | 
				
			||||||
dotenv.read_dotenv("{0}/.env".format(PROJECT_DIR))
 | 
					dotenv.read_dotenv("{0}/.env".format(PROJECT_DIR))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SITE_ID = 1
 | 
					from multisite import SiteID
 | 
				
			||||||
 | 
					SITE_ID = SiteID(default=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
APP_ROOT_ENDPOINT = "/"
 | 
					APP_ROOT_ENDPOINT = "/"
 | 
				
			||||||
APPEND_SLASH = True
 | 
					APPEND_SLASH = True
 | 
				
			||||||
| 
						 | 
					@ -76,6 +78,7 @@ SECRET_KEY = env('DJANGO_SECRET_KEY')
 | 
				
			||||||
INSTALLED_APPS = (
 | 
					INSTALLED_APPS = (
 | 
				
			||||||
    # 1st migrate
 | 
					    # 1st migrate
 | 
				
			||||||
    'membership',
 | 
					    'membership',
 | 
				
			||||||
 | 
					    'djangocms_admin_style',
 | 
				
			||||||
    'django.contrib.admin',
 | 
					    'django.contrib.admin',
 | 
				
			||||||
    'django.contrib.auth',
 | 
					    'django.contrib.auth',
 | 
				
			||||||
    'django.contrib.contenttypes',
 | 
					    'django.contrib.contenttypes',
 | 
				
			||||||
| 
						 | 
					@ -83,6 +86,8 @@ INSTALLED_APPS = (
 | 
				
			||||||
    'django.contrib.messages',
 | 
					    'django.contrib.messages',
 | 
				
			||||||
    'django.contrib.staticfiles',
 | 
					    'django.contrib.staticfiles',
 | 
				
			||||||
    'django.contrib.sites',
 | 
					    'django.contrib.sites',
 | 
				
			||||||
 | 
					    'multisite',
 | 
				
			||||||
 | 
					    'djangocms_multisite',
 | 
				
			||||||
    'easy_thumbnails',
 | 
					    'easy_thumbnails',
 | 
				
			||||||
    'utils',
 | 
					    'utils',
 | 
				
			||||||
    'stored_messages',
 | 
					    'stored_messages',
 | 
				
			||||||
| 
						 | 
					@ -124,7 +129,6 @@ INSTALLED_APPS = (
 | 
				
			||||||
    # 'djangocms_teaser',
 | 
					    # 'djangocms_teaser',
 | 
				
			||||||
    'djangocms_page_meta',
 | 
					    'djangocms_page_meta',
 | 
				
			||||||
    'djangocms_text_ckeditor',
 | 
					    'djangocms_text_ckeditor',
 | 
				
			||||||
    'djangocms_admin_style',
 | 
					 | 
				
			||||||
    'cmsplugin_filer_file',
 | 
					    'cmsplugin_filer_file',
 | 
				
			||||||
    'cmsplugin_filer_folder',
 | 
					    'cmsplugin_filer_folder',
 | 
				
			||||||
    'cmsplugin_filer_link',
 | 
					    'cmsplugin_filer_link',
 | 
				
			||||||
| 
						 | 
					@ -163,6 +167,8 @@ MIDDLEWARE_CLASSES = (
 | 
				
			||||||
    'cms.middleware.page.CurrentPageMiddleware',
 | 
					    'cms.middleware.page.CurrentPageMiddleware',
 | 
				
			||||||
    'cms.middleware.toolbar.ToolbarMiddleware',
 | 
					    'cms.middleware.toolbar.ToolbarMiddleware',
 | 
				
			||||||
    'cms.middleware.language.LanguageCookieMiddleware',
 | 
					    'cms.middleware.language.LanguageCookieMiddleware',
 | 
				
			||||||
 | 
					    'multisite.middleware.DynamicSiteMiddleware',
 | 
				
			||||||
 | 
					    'djangocms_multisite.middleware.CMSMultiSiteMiddleware',
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CSRF_FAILURE_VIEW = 'hosting.views.forbidden_view'
 | 
					CSRF_FAILURE_VIEW = 'hosting.views.forbidden_view'
 | 
				
			||||||
| 
						 | 
					@ -328,6 +334,8 @@ CMS_PLACEHOLDER_CONF = {
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CMS_PERMISSION=True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CACHES = {
 | 
					CACHES = {
 | 
				
			||||||
    'default': {
 | 
					    'default': {
 | 
				
			||||||
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
 | 
					        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
 | 
				
			||||||
| 
						 | 
					@ -507,6 +515,36 @@ STRIPE_API_PRIVATE_KEY_TEST = env('STRIPE_API_PRIVATE_KEY_TEST')
 | 
				
			||||||
ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch'
 | 
					ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch'
 | 
				
			||||||
GUARDIAN_GET_INIT_ANONYMOUS_USER = 'membership.models.get_anonymous_user_instance'
 | 
					GUARDIAN_GET_INIT_ANONYMOUS_USER = 'membership.models.get_anonymous_user_instance'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UNGLEICH_SITE_CONFIGS = env('UNGLEICH_SITE_CONFIGS')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MULTISITE_CMS_URLS = {}
 | 
				
			||||||
 | 
					if UNGLEICH_SITE_CONFIGS == "":
 | 
				
			||||||
 | 
					    raise Exception("Please define UNGLEICH_SITE_CONFIGS in your .env")
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        configs_dict=json.loads(UNGLEICH_SITE_CONFIGS)
 | 
				
			||||||
 | 
					    except ValueError as verr:
 | 
				
			||||||
 | 
					        raise Exception("UNGLEICH_SITE_CONFIGS is not a valid JSON: {}".format(
 | 
				
			||||||
 | 
					            str(verr)
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        MULTISITE_CMS_URLS = {
 | 
				
			||||||
 | 
					            k:v['MULTISITE_CMS_URL'] for (k,v) in configs_dict.items()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MULTISITE_CMS_ALIASES = {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					MULTISITE_CMS_FALLBACK = env('MULTISITE_CMS_FALLBACK')
 | 
				
			||||||
 | 
					if MULTISITE_CMS_FALLBACK == '':
 | 
				
			||||||
 | 
					    MULTISITE_CMS_FALLBACK = 'datacenterlight.ch'
 | 
				
			||||||
 | 
					MULTISITE_FALLBACK = 'django.views.generic.base.RedirectView'
 | 
				
			||||||
 | 
					MULTISITE_FALLBACK_KWARGS = {
 | 
				
			||||||
 | 
					    'url': 'https://{}/'.format(MULTISITE_CMS_FALLBACK), 'permanent': False
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FILER_ENABLE_PERMISSIONS = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#############################################
 | 
					#############################################
 | 
				
			||||||
# configurations for opennebula-integration #
 | 
					# configurations for opennebula-integration #
 | 
				
			||||||
#############################################
 | 
					#############################################
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,5 +19,6 @@ MIDDLEWARE_CLASSES += ("debug_toolbar.middleware.DebugToolbarMiddleware",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSTALLED_APPS += (
 | 
					INSTALLED_APPS += (
 | 
				
			||||||
    'django_extensions',
 | 
					    'django_extensions',
 | 
				
			||||||
    'debug_toolbar'
 | 
					    # debug_toolbar seems to conflict with multisite (and djangocms_multisite)
 | 
				
			||||||
 | 
					    #   'debug_toolbar'
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,5 +31,6 @@ ALLOWED_HOSTS = [
 | 
				
			||||||
    ".ipv6onlyhosting.com",
 | 
					    ".ipv6onlyhosting.com",
 | 
				
			||||||
    ".ipv6onlyhosting.net",
 | 
					    ".ipv6onlyhosting.net",
 | 
				
			||||||
    ".digitalglarus.ch",
 | 
					    ".digitalglarus.ch",
 | 
				
			||||||
    ".hack4glarus.ch"
 | 
					    ".hack4glarus.ch",
 | 
				
			||||||
 | 
					    ".xn--nglarus-n2a.ch"
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								dynamicweb/urls_multi.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								dynamicweb/urls_multi.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					from django.conf.urls import include, url
 | 
				
			||||||
 | 
					from django.conf.urls.i18n import i18n_patterns
 | 
				
			||||||
 | 
					from django.contrib import admin
 | 
				
			||||||
 | 
					from django.views import static as static_view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					urlpatterns = i18n_patterns(
 | 
				
			||||||
 | 
					    url(r'^admin/', include(admin.site.urls)),
 | 
				
			||||||
 | 
					    url(r'^cms/', include('cms.urls')),
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					urlpatterns += [
 | 
				
			||||||
 | 
					    url(r'^media/(?P<path>.*)$',
 | 
				
			||||||
 | 
					        static_view.serve, {
 | 
				
			||||||
 | 
					            'document_root': settings.MEDIA_ROOT,
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,103 @@
 | 
				
			||||||
 | 
					from django import forms
 | 
				
			||||||
from django.contrib import admin
 | 
					from django.contrib import admin
 | 
				
			||||||
 | 
					from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
 | 
				
			||||||
 | 
					from django.contrib.auth.forms import ReadOnlyPasswordHashField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import CustomUser, StripeCustomer
 | 
					from .models import CustomUser, StripeCustomer
 | 
				
			||||||
from django.contrib.auth.hashers import make_password
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CustomUserAdmin(admin.ModelAdmin):
 | 
					# Refer https://docs.djangoproject.com/en/2.0/topics/auth/customizing/
 | 
				
			||||||
    fields = ('password', 'user_permissions', 'email', 'is_admin')
 | 
					# for understanding custom auth user model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save_model(self, request, obj, form, change):
 | 
					 | 
				
			||||||
        password = form.cleaned_data.get('password')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not change:
 | 
					class UserCreationForm(forms.ModelForm):
 | 
				
			||||||
            obj.validation_slug = make_password(None)
 | 
					    """A form for creating new users. Includes all the required
 | 
				
			||||||
 | 
					    fields, plus a repeated password."""
 | 
				
			||||||
 | 
					    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
 | 
				
			||||||
 | 
					    password2 = forms.CharField(label='Password confirmation',
 | 
				
			||||||
 | 
					                                widget=forms.PasswordInput)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        obj.set_password(password)
 | 
					    class Meta:
 | 
				
			||||||
        obj.save()
 | 
					        model = CustomUser
 | 
				
			||||||
        return obj
 | 
					        fields = ('email', 'user_permissions', 'email', 'is_admin')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean_password2(self):
 | 
				
			||||||
 | 
					        # Check that the two password entries match
 | 
				
			||||||
 | 
					        password1 = self.cleaned_data.get("password1")
 | 
				
			||||||
 | 
					        password2 = self.cleaned_data.get("password2")
 | 
				
			||||||
 | 
					        if password1 and password2 and password1 != password2:
 | 
				
			||||||
 | 
					            raise forms.ValidationError("Passwords don't match")
 | 
				
			||||||
 | 
					        return password2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save(self, commit=True):
 | 
				
			||||||
 | 
					        # Save the provided password in hashed format
 | 
				
			||||||
 | 
					        user = super().save(commit=False)
 | 
				
			||||||
 | 
					        user.set_password(self.cleaned_data["password1"])
 | 
				
			||||||
 | 
					        if commit:
 | 
				
			||||||
 | 
					            user.save()
 | 
				
			||||||
 | 
					        return user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserChangeForm(forms.ModelForm):
 | 
				
			||||||
 | 
					    """A form for updating users. Includes all the fields on
 | 
				
			||||||
 | 
					    the user, but replaces the password field with admin's
 | 
				
			||||||
 | 
					    password hash display field.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    password = ReadOnlyPasswordHashField(
 | 
				
			||||||
 | 
					        label="Password",
 | 
				
			||||||
 | 
					        help_text=(
 | 
				
			||||||
 | 
					            "Raw passwords are not stored, so there is no way to see "
 | 
				
			||||||
 | 
					            "this user's password, but you can change the password "
 | 
				
			||||||
 | 
					            "using <a href=\"../password/\">this form</a>.")
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = CustomUser
 | 
				
			||||||
 | 
					        fields = ('email', 'password', 'is_admin')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean_password(self):
 | 
				
			||||||
 | 
					        # Regardless of what the user provides, return the initial value.
 | 
				
			||||||
 | 
					        # This is done here, rather than on the field, because the
 | 
				
			||||||
 | 
					        # field does not have access to the initial value
 | 
				
			||||||
 | 
					        return self.initial["password"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CustomUserAdmin(BaseUserAdmin):
 | 
				
			||||||
 | 
					    # The forms to add and change user instances
 | 
				
			||||||
 | 
					    form = UserChangeForm
 | 
				
			||||||
 | 
					    add_form = UserCreationForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # The fields to be used in displaying the User model.
 | 
				
			||||||
 | 
					    # These override the definitions on the base UserAdmin
 | 
				
			||||||
 | 
					    # that reference specific fields on auth.User.
 | 
				
			||||||
 | 
					    list_display = (
 | 
				
			||||||
 | 
					        'email', 'is_admin', 'is_superuser'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    list_filter = ()
 | 
				
			||||||
 | 
					    fieldsets = (
 | 
				
			||||||
 | 
					        (None, {'fields': ('email',)}),
 | 
				
			||||||
 | 
					        ('Change Password',
 | 
				
			||||||
 | 
					         {'fields': ('password',),
 | 
				
			||||||
 | 
					          'description': "Raw passwords are not stored, so there is no way to "
 | 
				
			||||||
 | 
					                         "see this user's password, but you can change the "
 | 
				
			||||||
 | 
					                         "password using <a href=\"../password/\">this "
 | 
				
			||||||
 | 
					                         "form</a>."
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					         ),
 | 
				
			||||||
 | 
					        ('Permissions', {'fields': ('is_admin', 'user_permissions',
 | 
				
			||||||
 | 
					                                    'groups')}),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
 | 
				
			||||||
 | 
					    # overrides get_fieldsets to use this attribute when creating a user.
 | 
				
			||||||
 | 
					    add_fieldsets = (
 | 
				
			||||||
 | 
					        (None, {
 | 
				
			||||||
 | 
					            'classes': ('wide',),
 | 
				
			||||||
 | 
					            'fields': ('email', 'password1', 'password2')}
 | 
				
			||||||
 | 
					         ),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    search_fields = ('email',)
 | 
				
			||||||
 | 
					    ordering = ('email',)
 | 
				
			||||||
 | 
					    filter_horizontal = ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
admin.site.register(CustomUser, CustomUserAdmin)
 | 
					admin.site.register(CustomUser, CustomUserAdmin)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										21
									
								
								membership/migrations/0007_auto_20180213_0128.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								membership/migrations/0007_auto_20180213_0128.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2018-02-13 01:28
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					import membership.models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('membership', '0006_auto_20160526_0445'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AlterField(
 | 
				
			||||||
 | 
					            model_name='customuser',
 | 
				
			||||||
 | 
					            name='validation_slug',
 | 
				
			||||||
 | 
					            field=models.CharField(db_index=True, default=membership.models.get_validation_slug, max_length=50, unique=True),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,10 @@ class MyUserManager(BaseUserManager):
 | 
				
			||||||
        return user
 | 
					        return user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_validation_slug():
 | 
				
			||||||
 | 
					    return make_password(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CustomUser(AbstractBaseUser, PermissionsMixin):
 | 
					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)
 | 
				
			||||||
| 
						 | 
					@ -66,8 +70,12 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
 | 
				
			||||||
    email = models.EmailField(unique=True)
 | 
					    email = models.EmailField(unique=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    validated = models.IntegerField(choices=VALIDATED_CHOICES, default=0)
 | 
					    validated = models.IntegerField(choices=VALIDATED_CHOICES, default=0)
 | 
				
			||||||
    validation_slug = models.CharField(db_index=True, unique=True,
 | 
					    # By default, we initialize the validation_slug with appropriate value
 | 
				
			||||||
                                       max_length=50)
 | 
					    # This is required for User(page) admin
 | 
				
			||||||
 | 
					    validation_slug = models.CharField(
 | 
				
			||||||
 | 
					        db_index=True, unique=True, max_length=50,
 | 
				
			||||||
 | 
					        default=get_validation_slug
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
    is_admin = models.BooleanField(
 | 
					    is_admin = models.BooleanField(
 | 
				
			||||||
        _('staff status'),
 | 
					        _('staff status'),
 | 
				
			||||||
        default=False,
 | 
					        default=False,
 | 
				
			||||||
| 
						 | 
					@ -171,6 +179,10 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
 | 
				
			||||||
        # Simplest possible answer: All admins are staff
 | 
					        # Simplest possible answer: All admins are staff
 | 
				
			||||||
        return self.is_admin
 | 
					        return self.is_admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @is_staff.setter
 | 
				
			||||||
 | 
					    def is_staff(self, value):
 | 
				
			||||||
 | 
					        self._is_staff = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StripeCustomer(models.Model):
 | 
					class StripeCustomer(models.Model):
 | 
				
			||||||
    user = models.OneToOneField(CustomUser)
 | 
					    user = models.OneToOneField(CustomUser)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,7 @@ class VirtualMachineSerializer(serializers.Serializer):
 | 
				
			||||||
            disk_size += int(disk.size)
 | 
					            disk_size += int(disk.size)
 | 
				
			||||||
        return disk_size / 1024
 | 
					        return disk_size / 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_sdd_size(self, obj):
 | 
					    def get_ssd_size(self, obj):
 | 
				
			||||||
        template = obj.template
 | 
					        template = obj.template
 | 
				
			||||||
        disk_size = 0
 | 
					        disk_size = 0
 | 
				
			||||||
        for disk in template.disks:
 | 
					        for disk in template.disks:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@ django-meta==1.2
 | 
				
			||||||
django-meta-mixin==0.3.0
 | 
					django-meta-mixin==0.3.0
 | 
				
			||||||
django-model-utils==2.5
 | 
					django-model-utils==2.5
 | 
				
			||||||
django-mptt==0.8.4
 | 
					django-mptt==0.8.4
 | 
				
			||||||
 | 
					django-multisite==1.4.1
 | 
				
			||||||
django-parler==1.6.3
 | 
					django-parler==1.6.3
 | 
				
			||||||
django-phonenumber-field==1.1.0
 | 
					django-phonenumber-field==1.1.0
 | 
				
			||||||
django-polymorphic==0.9.2
 | 
					django-polymorphic==0.9.2
 | 
				
			||||||
| 
						 | 
					@ -97,3 +98,4 @@ billiard==3.5.0.3
 | 
				
			||||||
amqp==2.2.1
 | 
					amqp==2.2.1
 | 
				
			||||||
vine==1.1.4
 | 
					vine==1.1.4
 | 
				
			||||||
cdist==4.7.0
 | 
					cdist==4.7.0
 | 
				
			||||||
 | 
					git+https://github.com/ungleich/djangocms-multisite.git#egg=djangocms_multisite
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ from .models import (
 | 
				
			||||||
    UngleichCustomerItem, UngleichHTMLOnly,
 | 
					    UngleichCustomerItem, UngleichHTMLOnly,
 | 
				
			||||||
    UngleichHeaderWithBackgroundImageSlider,
 | 
					    UngleichHeaderWithBackgroundImageSlider,
 | 
				
			||||||
    UngleichHeaderWithBackgroundVideoSliderItem,
 | 
					    UngleichHeaderWithBackgroundVideoSliderItem,
 | 
				
			||||||
 | 
					    UngleichFooter
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,3 +296,18 @@ class UngleichHTMLPlugin(CMSPluginBase):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        context['instance'] = instance
 | 
					        context['instance'] = instance
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@plugin_pool.register_plugin
 | 
				
			||||||
 | 
					class UngleichFooterPlugin(CMSPluginBase):
 | 
				
			||||||
 | 
					    name = "ungleich Footer Plugin"
 | 
				
			||||||
 | 
					    model = UngleichFooter
 | 
				
			||||||
 | 
					    render_template = "ungleich_page/ungleich/_footer.html"
 | 
				
			||||||
 | 
					    cache = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def render(self, context, instance, placeholder):
 | 
				
			||||||
 | 
					        context = super(UngleichFooterPlugin, self).render(
 | 
				
			||||||
 | 
					            context, instance, placeholder
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        context['instance'] = instance
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										44
									
								
								ungleich_page/migrations/0018_ungleichfooter.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								ungleich_page/migrations/0018_ungleichfooter.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2018-02-08 15:49
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					import django.db.models.deletion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('ungleich_page', '0017_auto_20171219_1856'),
 | 
				
			||||||
 | 
					        ('cms', '0014_auto_20160404_1908'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.CreateModel(
 | 
				
			||||||
 | 
					            name='UngleichFooter',
 | 
				
			||||||
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ('cmsplugin_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE,
 | 
				
			||||||
 | 
					                                                       parent_link=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
 | 
				
			||||||
 | 
					                ('copyright_label', models.CharField(blank=True, default='',
 | 
				
			||||||
 | 
					                                                     help_text='Name of the company alongside the copyright year', max_length=100)),
 | 
				
			||||||
 | 
					                ('link_text', models.CharField(
 | 
				
			||||||
 | 
					                    blank=True, help_text='Text for the link on the right part of footer', max_length=100, null=True)),
 | 
				
			||||||
 | 
					                ('link_url', models.URLField(blank=True,
 | 
				
			||||||
 | 
					                                             help_text='Url to the link in footer', null=True)),
 | 
				
			||||||
 | 
					                ('twitter_url', models.URLField(
 | 
				
			||||||
 | 
					                    blank=True, help_text='If empty, twitter btn will not be visible', null=True)),
 | 
				
			||||||
 | 
					                ('linkedin_url', models.URLField(
 | 
				
			||||||
 | 
					                    blank=True, help_text='If empty, linkedin btn will not be visible', null=True)),
 | 
				
			||||||
 | 
					                ('github_url', models.URLField(
 | 
				
			||||||
 | 
					                    blank=True, help_text='If empty, github btn will not be visible', null=True)),
 | 
				
			||||||
 | 
					                ('facebook_url', models.URLField(
 | 
				
			||||||
 | 
					                    blank=True, help_text='If empty, facebook btn will not be visible', null=True)),
 | 
				
			||||||
 | 
					                ('youtube_url', models.URLField(
 | 
				
			||||||
 | 
					                    blank=True, help_text='If empty, youtube btn will not be visible', null=True)),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            options={
 | 
				
			||||||
 | 
					                'abstract': False,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            bases=('cms.cmsplugin',),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
							
								
								
									
										16
									
								
								ungleich_page/migrations/0019_merge.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								ungleich_page/migrations/0019_merge.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					# Generated by Django 1.9.4 on 2018-02-08 20:10
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('ungleich_page', '0018_ungleichfooter'),
 | 
				
			||||||
 | 
					        ('ungleich_page', '0018_auto_20180105_1826'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
| 
						 | 
					@ -169,3 +169,38 @@ class UngleichHTMLOnly(CMSPlugin):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.name
 | 
					        return self.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UngleichFooter(CMSPlugin):
 | 
				
			||||||
 | 
					    copyright_label = models.CharField(
 | 
				
			||||||
 | 
					        max_length=100, default='', blank=True,
 | 
				
			||||||
 | 
					        help_text='Name of the company alongside the copyright year'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    link_text = models.CharField(
 | 
				
			||||||
 | 
					        max_length=100, blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='Text for the link on the right part of footer'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    link_url = models.URLField(
 | 
				
			||||||
 | 
					        blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='Url to the link in footer'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    twitter_url = models.URLField(
 | 
				
			||||||
 | 
					        blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='If empty, twitter btn will not be visible'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    linkedin_url = models.URLField(
 | 
				
			||||||
 | 
					        blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='If empty, linkedin btn will not be visible'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    github_url = models.URLField(
 | 
				
			||||||
 | 
					        blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='If empty, github btn will not be visible'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    facebook_url = models.URLField(
 | 
				
			||||||
 | 
					        blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='If empty, facebook btn will not be visible'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    youtube_url = models.URLField(
 | 
				
			||||||
 | 
					        blank=True, null=True,
 | 
				
			||||||
 | 
					        help_text='If empty, youtube btn will not be visible'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										47
									
								
								ungleich_page/templates/ungleich_page/ungleich/_footer.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								ungleich_page/templates/ungleich_page/ungleich/_footer.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					<footer>
 | 
				
			||||||
 | 
						<div class="container">
 | 
				
			||||||
 | 
							<div class="row">
 | 
				
			||||||
 | 
							  <div class="col-md-4">
 | 
				
			||||||
 | 
							    <span class="copyright">Copyright © {{instance.copyright_label}} {% now "Y" %}</span>
 | 
				
			||||||
 | 
							  </div>
 | 
				
			||||||
 | 
							  <div class="col-md-4">
 | 
				
			||||||
 | 
							    <ul class="list-inline social-buttons">
 | 
				
			||||||
 | 
							    	{% if instance.twitter_url %}
 | 
				
			||||||
 | 
								      <li>
 | 
				
			||||||
 | 
								      	<a href="{{instance.twitter_url}}"><i class="fa fa-twitter"></i></a>
 | 
				
			||||||
 | 
								      </li>
 | 
				
			||||||
 | 
							    	{% endif %}
 | 
				
			||||||
 | 
							    	{% if instance.github_url %}
 | 
				
			||||||
 | 
								      <li>
 | 
				
			||||||
 | 
								      	<a href="{{instance.github_url}}"><i class="fa fa-github"></i></a>
 | 
				
			||||||
 | 
								      </li>
 | 
				
			||||||
 | 
							    	{% endif %}
 | 
				
			||||||
 | 
							    	{% if instance.linkedin_url %}
 | 
				
			||||||
 | 
								      <li>
 | 
				
			||||||
 | 
								      	<a href="{{instance.linkedin_url}}"><i class="fa fa-linkedin"></i></a>
 | 
				
			||||||
 | 
								      </li>
 | 
				
			||||||
 | 
							    	{% endif %}
 | 
				
			||||||
 | 
							    	{% if instance.facebook_url %}
 | 
				
			||||||
 | 
								      <li>
 | 
				
			||||||
 | 
								      	<a href="{{instance.facebook_url}}"><i class="fa fa-facebook"></i></a>
 | 
				
			||||||
 | 
								      </li>
 | 
				
			||||||
 | 
							    	{% endif %}
 | 
				
			||||||
 | 
							    	{% if instance.youtube_url %}
 | 
				
			||||||
 | 
								      <li>
 | 
				
			||||||
 | 
								      	<a href="{{instance.youtube_url}}"><i class="fa fa-youtube-play"></i></a>
 | 
				
			||||||
 | 
								      </li>
 | 
				
			||||||
 | 
							    	{% endif %}
 | 
				
			||||||
 | 
							    </ul>
 | 
				
			||||||
 | 
							  </div>
 | 
				
			||||||
 | 
							  <div class="col-md-4">
 | 
				
			||||||
 | 
							  	{% if instance.link_text %}
 | 
				
			||||||
 | 
								    <ul class="list-inline quicklinks">
 | 
				
			||||||
 | 
								      <li>
 | 
				
			||||||
 | 
										<a href="{{instance.link_url}}">{{instance.link_text}}</a>
 | 
				
			||||||
 | 
								      </li>
 | 
				
			||||||
 | 
								    </ul>
 | 
				
			||||||
 | 
							  	{% endif %}
 | 
				
			||||||
 | 
							  </div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</footer>
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,9 @@
 | 
				
			||||||
    {% placeholder 'Ungleich Page Contents' %}
 | 
					    {% placeholder 'Ungleich Page Contents' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Footer -->
 | 
					    <!-- Footer -->
 | 
				
			||||||
 | 
					    {% placeholder 'Footer' or %}
 | 
				
			||||||
        {% include "ungleich_page/includes/_footer.html" %}
 | 
					        {% include "ungleich_page/includes/_footer.html" %}
 | 
				
			||||||
 | 
					    {% endplaceholder %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- jQuery -->
 | 
					    <!-- jQuery -->
 | 
				
			||||||
    <script src="{% static 'ungleich_page/js/jquery.js' %}" type="text/javascript"></script>
 | 
					    <script src="{% static 'ungleich_page/js/jquery.js' %}" type="text/javascript"></script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue