diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b87a1a4
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,35 @@
+Copyright 2020 Santiago Lamora and individual contributors.
+All Rights Reserved.
+
+django-musician is licensed under The BSD License (3 Clause, also known as
+the new BSD license). The license is an OSI approved Open Source
+license and is GPL-compatible(1).
+
+The license text can also be found here:
+http://www.opensource.org/licenses/BSD-3-Clause
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Ask Solem, nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/musician/__init__.py b/musician/__init__.py
index 4d761dc..d97a598 100644
--- a/musician/__init__.py
+++ b/musician/__init__.py
@@ -2,7 +2,7 @@
Package metadata definition.
"""
-VERSION = (0, 1, 0, 'beta', 1)
+VERSION = (0, 1, 0, 'beta', 2)
def get_version():
diff --git a/musician/api.py b/musician/api.py
index 8b4139c..bbf77a5 100644
--- a/musician/api.py
+++ b/musician/api.py
@@ -6,7 +6,7 @@ from django.http import Http404
from django.urls.exceptions import NoReverseMatch
from django.utils.translation import gettext_lazy as _
-from .models import Domain, DatabaseService, MailService, SaasService, UserAccount
+from .models import Domain, DatabaseService, MailService, SaasService, UserAccount, WebSite
DOMAINS_PATH = 'domains/'
@@ -25,6 +25,7 @@ API_PATHS = {
'mailbox-list': 'mailboxes/',
'mailinglist-list': 'lists/',
'saas-list': 'saas/',
+ 'website-list': 'websites/',
# other
'bill-list': 'bills/',
@@ -118,6 +119,8 @@ class Orchestra(object):
def retrieve_domain_list(self):
output = self.retrieve_service_list(Domain.api_name)
+ websites = self.retrieve_website_list()
+
domains = []
for domain_json in output:
# filter querystring
@@ -126,6 +129,10 @@ class Orchestra(object):
# retrieve services associated to a domain
domain_json['mails'] = self.retrieve_service_list(
MailService.api_name, querystring)
+
+ # retrieve websites (as they cannot be filtered by domain on the API we should do it here)
+ domain_json['websites'] = self.filter_websites_by_domain(websites, domain_json['id'])
+
# TODO(@slamora): databases and sass are not related to a domain, so cannot be filtered
# domain_json['databases'] = self.retrieve_service_list(DatabaseService.api_name, querystring)
# domain_json['saas'] = self.retrieve_service_list(SaasService.api_name, querystring)
@@ -143,6 +150,19 @@ class Orchestra(object):
return domains
+ def retrieve_website_list(self):
+ output = self.retrieve_service_list(WebSite.api_name)
+ return [WebSite.new_from_json(website_data) for website_data in output]
+
+ def filter_websites_by_domain(self, websites, domain_id):
+ matching = []
+ for website in websites:
+ web_domains = [web_domain.id for web_domain in website.domains]
+ if domain_id in web_domains:
+ matching.append(website)
+
+ return matching
+
def verify_credentials(self):
"""
Returns:
diff --git a/musician/models.py b/musician/models.py
index 039128c..de43a1a 100644
--- a/musician/models.py
+++ b/musician/models.py
@@ -1,6 +1,7 @@
import ast
import logging
+from django.utils.dateparse import parse_datetime
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
@@ -100,15 +101,20 @@ class UserAccount(OrchestraModel):
'short_name': None,
'full_name': None,
'billing': {},
+ 'last_login': None,
}
@classmethod
def new_from_json(cls, data, **kwargs):
billing = None
+ last_login = None
if 'billcontact' in data:
billing = BillingContact.new_from_json(data['billcontact'])
- return super().new_from_json(data=data, billing=billing)
+
+ if 'last_login' in data:
+ last_login = parse_datetime(data['last_login'])
+ return super().new_from_json(data=data, billing=billing, last_login=last_login)
class DatabaseUser(OrchestraModel):
@@ -157,6 +163,7 @@ class Domain(OrchestraModel):
"records": [],
"mails": [],
"usage": {},
+ "websites": [],
}
@classmethod
@@ -230,6 +237,7 @@ class MailinglistService(OrchestraModel):
fields = ('name', 'status', 'address_name', 'admin_email', 'configure')
param_defaults = {
'name': None,
+ 'is_active': True,
'admin_email': None,
}
@@ -237,11 +245,6 @@ class MailinglistService(OrchestraModel):
self.data = kwargs
super().__init__(**kwargs)
- @property
- def status(self):
- # TODO(@slamora): where retrieve if the list is active?
- return 'active'
-
@property
def address_name(self):
return "{}@{}".format(self.data['address_name'], self.data['address_domain']['name'])
@@ -262,3 +265,23 @@ class SaasService(OrchestraModel):
'is_active': True,
'data': {},
}
+
+
+class WebSite(OrchestraModel):
+ api_name = 'website'
+ param_defaults = {
+ "id": None,
+ "name": None,
+ "protocol": None,
+ "is_active": True,
+ "domains": [],
+ "contents": [],
+ }
+
+ @classmethod
+ def new_from_json(cls, data, **kwargs):
+ domains = cls.param_defaults.get("domains")
+ if 'domains' in data:
+ domains = [Domain.new_from_json(domain_data) for domain_data in data['domains']]
+
+ return super().new_from_json(data=data, domains=domains)
diff --git a/musician/static/musician/css/default.css b/musician/static/musician/css/default.css
index a9d7da4..a95a573 100644
--- a/musician/static/musician/css/default.css
+++ b/musician/static/musician/css/default.css
@@ -40,15 +40,34 @@ a:hover {
}
#sidebar {
- min-width: 250px;
- max-width: 250px;
+ min-width: 280px;
+ max-width: 280px;
min-height: 100vh;
+
+ display: flex;
+ flex-direction: column;
+}
+#sidebar #sidebar-services {
+ flex-grow: 1;
}
#sidebar.active {
margin-left: -250px;
}
+#sidebar .sidebar-branding {
+ padding-left: 2rem;
+ padding-right: 2rem;
+}
+#sidebar #sidebar-services {
+ padding-left: 1rem;
+ padding-right: 1rem;
+}
+
+#sidebar #user-profile-menu {
+ background:rgba(254, 251, 242, 0.25);
+}
+
#sidebar ul.components {
padding: 20px 0;
}
@@ -76,7 +95,7 @@ a:hover {
/** login **/
#body-login .jumbotron {
- background: #282532;/**#50466E;**/
+ background: #282532 no-repeat url("../images/logo-pangea-lilla-bg.svg") right;
}
#login-content {
@@ -104,8 +123,10 @@ a:hover {
}
#content {
- background: #ECECEB;
+ background: #ECECEB no-repeat url("../images/logo-pangea-light-gray-bg.svg");
+ background-position: right 5% top 10%;
color: #343434;
+ padding-left: 2rem;
}
/** services **/
diff --git a/musician/static/musician/images/logo-pangea-light-gray-bg.svg b/musician/static/musician/images/logo-pangea-light-gray-bg.svg
new file mode 100644
index 0000000..c4fe411
--- /dev/null
+++ b/musician/static/musician/images/logo-pangea-light-gray-bg.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/musician/static/musician/images/logo-pangea-lilla-bg.svg b/musician/static/musician/images/logo-pangea-lilla-bg.svg
new file mode 100644
index 0000000..3db2325
--- /dev/null
+++ b/musician/static/musician/images/logo-pangea-lilla-bg.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/musician/templates/musician/base.html b/musician/templates/musician/base.html
index 3782089..27a1eb8 100644
--- a/musician/templates/musician/base.html
+++ b/musician/templates/musician/base.html
@@ -11,7 +11,7 @@
{% endblock %}
-
{% block title %}{% if name %}{{ name }} – {% endif %}Django musician{% endblock %}
+ {% block title %}{% if title %}{{ title }} – {% endif %}Django musician{% endblock %}
{% block style %}
{% block bootstrap_theme %}
@@ -23,9 +23,6 @@
- {% if code_style %}{% endif %}
{% endblock %}
{% endblock %}
@@ -37,27 +34,27 @@