Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add custom domain #635

Merged
merged 9 commits into from
Jan 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deployment/sites-enabled/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ server {
# the port your site will be served on
listen 8080;
# the domain name it will serve for
server_name staging.projecta.kartoza.com changelog.linfiniti.com changelog.kartoza.com changelog.qgis.org changelog.inasafe.org staging.changelog.qgis.org;
server_name *;
charset utf-8;

# max upload size, adjust to taste
Expand Down
19 changes: 18 additions & 1 deletion django_project/base/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


from django.contrib import admin
from models import Project, ProjectScreenshot
from models import Project, ProjectScreenshot, Domain, Organisation
import reversion


Expand Down Expand Up @@ -46,4 +46,21 @@ def queryset(self, request):
return qs


class OrganisationAdmin(reversion.VersionAdmin):
"""Admin for the organisation model."""

def queryset(self, request):
"""Ensure we use the correct manager.

:param request: HttpRequest object
"""
qs = self.model.objects
ordering = self.get_ordering(request)
if ordering:
qs = qs.order_by(*ordering)
return qs


admin.site.register(Project, ProjectAdmin)
admin.site.register(Domain)
admin.site.register(Organisation, OrganisationAdmin)
77 changes: 76 additions & 1 deletion django_project/base/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
Layout,
Fieldset,
Field,
Submit,
)
from models import Project, ProjectScreenshot
from models import Project, ProjectScreenshot, Domain, Organisation
from certification.forms import CustomSelectMultipleWidget

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -78,6 +79,7 @@ class Meta:
model = Project
fields = (
'name',
'organisation',
'image_file',
'description',
'project_url',
Expand All @@ -100,6 +102,7 @@ def __init__(self, *args, **kwargs):
Fieldset(
'Project details',
Field('name', css_class="form-control"),
Field('organisation', css_class="form-control"),
Field('image_file', css_class="form-control"),
Field('description', css_class="form-control"),
Field('project_url', css_class="form-control"),
Expand Down Expand Up @@ -167,3 +170,75 @@ def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()


class RegisterDomainForm(forms.ModelForm):
"""Form to register a domain."""

# noinspection PyClassicStyleClass
class Meta:
"""Meta class."""
model = Domain
fields = (
'domain',
'role',
'project',
'organisation',
)

def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
form_title = 'Register a Domain'
self.helper = FormHelper()
layout = Layout(
Fieldset(
form_title,
Field('domain', css_class='form-control'),
Field('role', css_class='form-control'),
Field('project', css_class='form-control'),
Field('organisation', css_class='form-control'),
)
)
self.helper.layout = layout
self.helper.html5_required = False
super(RegisterDomainForm, self).__init__(*args, **kwargs)
self.helper.add_input(Submit('submit', 'Submit'))

def save(self, commit=True):
instance = super(RegisterDomainForm, self).save(commit=False)
instance.user = self.user
instance.save()
return instance


class OrganisationForm(forms.ModelForm):
"""Form to create an organisation that is associated to a project."""

# noinspection PyClassicStyleClass
class Meta:
"""Meta class."""
model = Organisation
fields = (
'name',
)

def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
form_title = 'Create an Organisation'
self.helper = FormHelper()
layout = Layout(
Fieldset(
form_title,
Field('name', css_class='form-control'),
)
)
self.helper.layout = layout
self.helper.html5_required = False
super(OrganisationForm, self).__init__(*args, **kwargs)
self.helper.add_input(Submit('submit', 'Submit'))

def save(self, commit=True):
instance = super(OrganisationForm, self).save(commit=False)
instance.owner = self.user
instance.save()
return instance
63 changes: 63 additions & 0 deletions django_project/base/migrations/0013_auto_20180103_0937.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
import base.models.project


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('base', '0012_project_sponsorship_manager'),
]

operations = [
migrations.CreateModel(
name='Domain',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('role', models.CharField(default=b'project', help_text='For organisation, domain will point to list of projects within the organisation and for project, domain will only point to a specific project.', max_length=30, choices=[(b'Project', b'Project'), (b'Organisation', b'Organisation')])),
('domain', models.CharField(help_text='Custom domain, i.e. projecta.kartoza.com.', unique=True, max_length=30)),
('approved', models.BooleanField(default=False, help_text='Whether this domain has been approved for use yet.')),
('paid', models.BooleanField(default=False, help_text='Whether this domain has been paid for use yet.')),
],
options={
'ordering': ['domain'],
},
),
migrations.CreateModel(
name='Organisation',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(help_text='Name of this organisation.', unique=True, max_length=150)),
('approved', models.BooleanField(default=False, help_text='Whether this organisation has been approved for use yet.')),
('owner', models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True)),
],
options={
'ordering': ['name'],
},
),
migrations.AddField(
model_name='domain',
name='organisation',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to='base.Organisation', null=True),
),
migrations.AddField(
model_name='domain',
name='project',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to='base.Project', null=True),
),
migrations.AddField(
model_name='domain',
name='user',
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='project',
name='organisation',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_DEFAULT, default=base.models.project.get_default_organisation, to='base.Organisation', null=True),
),
]
2 changes: 2 additions & 0 deletions django_project/base/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from project import * # noqa
from custom_domain import *
from organisation import *
69 changes: 69 additions & 0 deletions django_project/base/models/custom_domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# coding=utf-8
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _
from base.models import Project, Organisation


ROLE = (
('Project', 'Project'),
('Organisation', 'Organisation'),
)


class Domain(models.Model):
"""Model to save subscribed user and their custom domain."""

user = models.ForeignKey(User)
role = models.CharField(
help_text=_(
'For organisation, domain will point to list of projects within '
'the organisation and for project, domain will only point to '
'a specific project.'),
choices=ROLE,
default='project',
blank=False,
null=False,
max_length=30
)

domain = models.CharField(
help_text=_('Custom domain, i.e. projecta.kartoza.com.'),
max_length=30,
null=False,
blank=False,
unique=True,
)

project = models.ForeignKey(
Project,
null=True,
blank=True,
on_delete=models.SET_NULL
)

organisation = models.ForeignKey(
Organisation,
null=True,
blank=True,
on_delete=models.SET_NULL
)

approved = models.BooleanField(
help_text=_('Whether this domain has been approved for use yet.'),
default=False
)

paid = models.BooleanField(
help_text=_('Whether this domain has been paid for use yet.'),
default=False
)

class Meta:
ordering = ['domain']

def save(self, *args, **kwargs):
super(Domain, self).save(*args, **kwargs)

def __unicode__(self):
return self.domain
35 changes: 35 additions & 0 deletions django_project/base/models/organisation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# coding=utf-8
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Organisation(models.Model):
"""Organisation where the project belongs."""

name = models.CharField(
help_text=_('Name of this organisation.'),
max_length=150,
null=False,
blank=False,
unique=True
)

approved = models.BooleanField(
help_text=_(
'Whether this organisation has been approved for use yet.'),
default=False
)

owner = models.ForeignKey(User, null=True, blank=True)

# noinspection PyClassicStyleClass
class Meta:
"""Meta class for project."""
ordering = ['name']

def save(self, *args, **kwargs):
super(Organisation, self).save(*args, **kwargs)

def __unicode__(self):
return u'{}'.format(self.name)
20 changes: 20 additions & 0 deletions django_project/base/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from django.conf import settings
from django.core.exceptions import ValidationError
from unidecode import unidecode
from organisation import Organisation

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -65,6 +66,16 @@ def validate_gitter_room_name(value):
)


def get_default_organisation():
# The owner of the default organisation is purposely empty because in the
# unittest it raises error since there are duplicates. But the owner of
# default organisation can be changed in the live site.

organisation = \
Organisation.objects.get_or_create(name='Kartoza', approved=True)[0]
return organisation.pk


class Project(models.Model):
"""A project model e.g. QGIS, InaSAFE etc."""

Expand Down Expand Up @@ -181,6 +192,15 @@ class Project(models.Model):
' the same permissions as project owner in the certification app.')
)

# Organisation where a project belongs, when the organisation is deleted,
# the project will automatically belongs to default organisation.
organisation = models.ForeignKey(
Organisation,
default=get_default_organisation,
null=True,
on_delete=models.SET_DEFAULT,
)

owner = models.ForeignKey(User)
slug = models.SlugField(unique=True)
objects = models.Manager()
Expand Down
19 changes: 19 additions & 0 deletions django_project/base/templates/custom_domain/domain-not-found.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% extends "project_base.html" %}
{% load staticfiles %}
{% load crispy_forms_tags %}

{% block page_title %}
<h1>Domain not found</h1>
{% endblock page_title %}

{% block content %}
<style>
.btn-register:hover {
background: #2B6FB6;
color: white;
border-color: #0A246A;
}
</style>
<h2 style="text-align: center">Custom domain registration</h2>
<h4 style="text-align: center; margin-top: 50px">Sorry, your domain is not registered in our system. <br/>If you like to use your own domain please register <a href="{% url 'register-domain' %}" class="btn btn-default btn-register">here</a></h4>
{% endblock %}
Loading