From b26a3548fcc913a39022e02b8ab88ad49783254f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 20 Dec 2016 01:40:01 +0100 Subject: [PATCH] start developing the control module --- src/c3nav/control/apps.py | 5 -- .../static/control/css/c3nav-control.css | 11 +++++ src/c3nav/control/templates/control/base.html | 47 ++++--------------- .../control/templates/control/dashboard.html | 4 -- .../control/templates/control/login.html | 24 ++++++++++ .../control/templates/control/prove.html | 41 ++++++++++++++++ src/c3nav/control/urls.py | 6 ++- src/c3nav/control/views.py | 37 ++++++++++++++- src/c3nav/editor/hosters/base.py | 7 +++ src/c3nav/editor/hosters/github.py | 4 ++ src/c3nav/editor/hosters/gitlab.py | 9 ++++ src/c3nav/mapdata/permissions.py | 5 ++ src/c3nav/site/static/site/css/c3nav.css | 5 ++ src/c3nav/site/static/site/js/c3nav.js | 4 +- src/c3nav/site/templates/site/base.html | 2 +- src/c3nav/site/templates/site/main.html | 2 +- 16 files changed, 160 insertions(+), 53 deletions(-) delete mode 100644 src/c3nav/control/apps.py create mode 100644 src/c3nav/control/static/control/css/c3nav-control.css delete mode 100644 src/c3nav/control/templates/control/dashboard.html create mode 100644 src/c3nav/control/templates/control/login.html create mode 100644 src/c3nav/control/templates/control/prove.html diff --git a/src/c3nav/control/apps.py b/src/c3nav/control/apps.py deleted file mode 100644 index a5f70859..00000000 --- a/src/c3nav/control/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class ControlConfig(AppConfig): - name = 'control' diff --git a/src/c3nav/control/static/control/css/c3nav-control.css b/src/c3nav/control/static/control/css/c3nav-control.css new file mode 100644 index 00000000..2454d7e7 --- /dev/null +++ b/src/c3nav/control/static/control/css/c3nav-control.css @@ -0,0 +1,11 @@ +body { + font-size:16px; +} + +h1 { + margin-bottom:20px; +} + +.login .container { + max-width:420px; +} diff --git a/src/c3nav/control/templates/control/base.html b/src/c3nav/control/templates/control/base.html index 48c62fc8..6bbdc38c 100644 --- a/src/c3nav/control/templates/control/base.html +++ b/src/c3nav/control/templates/control/base.html @@ -6,51 +6,24 @@ - c3nav Administration + c3nav control panel {% compress css %} - - + + {% endcompress %} - + - - -
- {% block content %} - {% endblock %} +
+

c3nav control panel

+ {% block content %} + {% endblock %}
{% compress js %} - - - - + + {% endcompress %} - {% block addbottom %} - {% endblock %} diff --git a/src/c3nav/control/templates/control/dashboard.html b/src/c3nav/control/templates/control/dashboard.html deleted file mode 100644 index 386a7d25..00000000 --- a/src/c3nav/control/templates/control/dashboard.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends 'control/base.html' %} -{% block content %} -

Dashboard

-{% endblock %} diff --git a/src/c3nav/control/templates/control/login.html b/src/c3nav/control/templates/control/login.html new file mode 100644 index 00000000..43ecbcd0 --- /dev/null +++ b/src/c3nav/control/templates/control/login.html @@ -0,0 +1,24 @@ +{% extends 'control/base.html' %} + +{% load bootstrap3 %} +{% load i18n %} + +{% block bodyclass %}login{% endblock %} + +{% block content %} +
+ {% csrf_token %} +
+ {% trans 'Log in' %} + {% bootstrap_form form %} +
+ +
+
+

{% blocktrans %}This is the non-public backend for creation of auth tokens.{% endblocktrans %}

+ +

+ {% blocktrans %}Prove that you should have access{% endblocktrans %} +

+
+{% endblock %} diff --git a/src/c3nav/control/templates/control/prove.html b/src/c3nav/control/templates/control/prove.html new file mode 100644 index 00000000..4cf685b7 --- /dev/null +++ b/src/c3nav/control/templates/control/prove.html @@ -0,0 +1,41 @@ +{% extends 'control/base.html' %} + +{% load bootstrap3 %} +{% load i18n %} + +{% block bodyclass %}login{% endblock %} + +{% block content %} +
+ {% csrf_token %} +
+ {% trans 'Prove access rights' %} +

{% blocktrans %}Please enter a valid authentication code for the hosters of the following non-public map packages:{% endblocktrans %}

+ {% if success %} +
+ {% trans 'Thanks – you get full access to the map!' %} +
+ {% elif hosters %} + {% if error %} +
+ + {% trans 'Sorry.' %} {% trans 'One or more access tokens were not correct.' %} +
+ {% endif %} + {% for package in hosters %} +
+ + +
+ {% endfor %} +
+ +
+ {% else %} +
+ {% trans 'Sorry, this service is currently not available.' %} +
+ {% endif %} +
+
+{% endblock %} diff --git a/src/c3nav/control/urls.py b/src/c3nav/control/urls.py index 174e3617..d18f897f 100644 --- a/src/c3nav/control/urls.py +++ b/src/c3nav/control/urls.py @@ -1,7 +1,11 @@ from django.conf.urls import url +from django.contrib.auth import views as auth_views -from c3nav.control.views import dashboard +from c3nav.control.views import dashboard, prove urlpatterns = [ url(r'^$', dashboard, name='control.dashboard'), + url(r'^prove/$', prove, name='control.prove'), + url(r'^login/$', auth_views.login, {'template_name': 'control/login.html'}, name='site.login'), + url(r'^logout/$', auth_views.logout, name='site.logout'), ] diff --git a/src/c3nav/control/views.py b/src/c3nav/control/views.py index 5f83b050..e2560691 100644 --- a/src/c3nav/control/views.py +++ b/src/c3nav/control/views.py @@ -1,7 +1,40 @@ -from django.contrib.admin.views.decorators import staff_member_required +from collections import OrderedDict + +from django.contrib.auth.decorators import login_required from django.shortcuts import render +from c3nav.editor.hosters import get_hoster_for_package +from c3nav.mapdata.permissions import get_nonpublic_packages -@staff_member_required + +@login_required(login_url='/control/login/') def dashboard(request): return render(request, 'control/dashboard.html') + + +def prove(request): + hosters = OrderedDict((package, get_hoster_for_package(package)) for package in get_nonpublic_packages()) + + if None in hosters.values(): + return render(request, 'control/prove.html', context={'hosters': None}) + + error = False + success = False + if request.method == 'POST': + user_ids = {} + for package, hoster in hosters.items(): + access_token = request.POST.get(package.name) + user_id = hoster.get_user_id_with_access_token(access_token) + if user_id is None: + error = True + break + user_ids[hoster] = user_id + + if not error: + success = True + + return render(request, 'control/prove.html', context={ + 'hosters': hosters, + 'error': error, + 'success': success, + }) diff --git a/src/c3nav/editor/hosters/base.py b/src/c3nav/editor/hosters/base.py index 600fd486..76018eea 100644 --- a/src/c3nav/editor/hosters/base.py +++ b/src/c3nav/editor/hosters/base.py @@ -157,3 +157,10 @@ class Hoster(ABC): message and an optional 'url' key containing an URL to the created pull request. """ pass + + @abstractmethod + def get_user_id_with_access_token(self, access_token) -> str: + """ + Get User ID of the User with this access token or None if the access token does not work. + """ + pass diff --git a/src/c3nav/editor/hosters/github.py b/src/c3nav/editor/hosters/github.py index 51f08a7a..31cb223c 100644 --- a/src/c3nav/editor/hosters/github.py +++ b/src/c3nav/editor/hosters/github.py @@ -192,3 +192,7 @@ class GithubHoster(Hoster): 'success': True, 'url': merge_request['html_url'] } + + def get_user_id_with_access_token(self, access_token): + # Todo: Implement this + return None diff --git a/src/c3nav/editor/hosters/gitlab.py b/src/c3nav/editor/hosters/gitlab.py index de808a36..b4e4cc52 100644 --- a/src/c3nav/editor/hosters/gitlab.py +++ b/src/c3nav/editor/hosters/gitlab.py @@ -139,3 +139,12 @@ class GitlabHoster(Hoster): 'success': True, 'url': merge_request['web_url'] } + + def get_user_id_with_access_token(self, access_token): + if not access_token.strip(): + return None + + response = requests.get(self.base_url + 'api/v3/user?private_token=' + access_token) + if response.status_code != 200: + return None + return str(response.json()['id']) diff --git a/src/c3nav/mapdata/permissions.py b/src/c3nav/mapdata/permissions.py index 870ccf21..bf3bf9e0 100644 --- a/src/c3nav/mapdata/permissions.py +++ b/src/c3nav/mapdata/permissions.py @@ -16,6 +16,11 @@ def get_public_packages(): return [packages_cached[name] for name in settings.PUBLIC_PACKAGES] +def get_nonpublic_packages(): + packages_cached = get_packages_cached() + return [package for name, package in packages_cached.items() if name not in settings.PUBLIC_PACKAGES] + + def get_unlocked_packages_names(request, packages_cached=None): if packages_cached is None: packages_cached = get_packages_cached() diff --git a/src/c3nav/site/static/site/css/c3nav.css b/src/c3nav/site/static/site/css/c3nav.css index b70e7986..8faaca0b 100644 --- a/src/c3nav/site/static/site/css/c3nav.css +++ b/src/c3nav/site/static/site/css/c3nav.css @@ -183,3 +183,8 @@ circle.pos { vertical-align:middle; line-height: 1.42857143; } + + +.login .container { + max-width:420px; +} diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index 6b10f8f3..46dc0015 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -1,5 +1,7 @@ c3nav = { init: function() { + if (!$('#c3nav-main').length) return; + c3nav._typeahead_locations = new Bloodhound({ datumTokenizer: function(data) { var result = [data.id] @@ -100,5 +102,3 @@ c3nav = { } }; $(document).ready(c3nav.init); - - diff --git a/src/c3nav/site/templates/site/base.html b/src/c3nav/site/templates/site/base.html index 2c01e5ad..0872e776 100644 --- a/src/c3nav/site/templates/site/base.html +++ b/src/c3nav/site/templates/site/base.html @@ -13,7 +13,7 @@ {% endcompress %} - +

c3nav

diff --git a/src/c3nav/site/templates/site/main.html b/src/c3nav/site/templates/site/main.html index 65c9b33b..aac0c101 100644 --- a/src/c3nav/site/templates/site/main.html +++ b/src/c3nav/site/templates/site/main.html @@ -4,7 +4,7 @@ {% load i18n %} {% block content %} -
+ {% csrf_token %}
{% trans "Origin" as heading %}