From f704f9bbd4a1c98b091f6bb54244f3ab3a67e8cb Mon Sep 17 00:00:00 2001 From: Lukas P Date: Thu, 25 Aug 2016 16:18:59 -0400 Subject: [PATCH 1/8] Modifies check marks in download button to toggle with css class Also adds fixed width for niceness --- html/static/css/download_keys.css | 15 ++++++++++++++- html/static/js/keys.js | 13 ++++--------- html/templates/download_keys.html | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/html/static/css/download_keys.css b/html/static/css/download_keys.css index 68ce386..ec20016 100644 --- a/html/static/css/download_keys.css +++ b/html/static/css/download_keys.css @@ -15,4 +15,17 @@ table { margin-left: 5%; -} \ No newline at end of file +} + +.button.key { + width: 230px; +} +.button.key:before, +.button.key:after { + content: ""; + display: inline-block; + width: 2em; +} +.button.key.checked:before { + content: "\2713"; +} diff --git a/html/static/js/keys.js b/html/static/js/keys.js index 9fafb28..3517e28 100644 --- a/html/static/js/keys.js +++ b/html/static/js/keys.js @@ -32,19 +32,14 @@ $(document).ready(function () { function addCheck(button) { /***************************************************************** - Adds a check mark to the button if one is not already there. + Adds class "checked" to button (passed as argument) to display + a lovely unicode check mark in front of the button text using + the :before pseudo element button: A button DOM element. - - Puts a lovely unicode check mark in front of the button text. None. *****************************************************************/ - - if ($(button).text().search(new RegExp(/[\u2713]/i)) != -1) { - return; - } - - $(button).html('✓ ' + $(button).html()); + $(button).addClass('checked'); } \ No newline at end of file diff --git a/html/templates/download_keys.html b/html/templates/download_keys.html index 42b00cd..1e1e883 100644 --- a/html/templates/download_keys.html +++ b/html/templates/download_keys.html @@ -16,12 +16,12 @@

Download user keys

{% if has_private_keys %} - {% if keys_downloaded.private %}✓ {% endif %}Download private keysYou must download an archive of the private keys that were generated for new users. + Download private keysYou must download an archive of the private keys that were generated for new users. {% endif %} - {% if keys_downloaded.public %}✓ {% endif %}Download public keysIt is strongly recommended that you download an archive of the public keys of all users. + Download public keysIt is strongly recommended that you download an archive of the public keys of all users. From 29b8b7364fb0238e5a7607fff17d3632843bb73f Mon Sep 17 00:00:00 2001 From: Lukas P Date: Fri, 26 Aug 2016 11:19:33 -0400 Subject: [PATCH 2/8] Adds combined download keys/download installer (fast lane) page Handy for e.g. Sensibility Hackathons in order to facilitate setup as described in: https://sensibilitytestbed.com/projects/project/wiki/setup The new view immediately builds a default installer and provides a download page for the according keys and installers --- html/templates/download_installers.html | 24 ++++++ html/urls.py | 1 + html/views.py | 97 ++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/html/templates/download_installers.html b/html/templates/download_installers.html index 06752bb..0a91b85 100644 --- a/html/templates/download_installers.html +++ b/html/templates/download_installers.html @@ -4,6 +4,12 @@ + +{# comment: On the fast lane we have installers and keys on one page #} +{% if fast_lane %} + + +{% endif %} {% endblock %} {% block content %} @@ -32,6 +38,24 @@

Thanks for contributing!

+ +{% if fast_lane %} +
+

Download user keys

+

For your reference, the Custom Installer Builder has generated ZIP archives of cryptographic keys associated with your installer. Once your browsing session expires, you cannot access these keys again.

+ + + + + + + + +
Download private keys
Download public keys
+ +
+{% endif %} {# comment: endif fast_lane #} +

Download installers

Installers are provided for Android, Linux, Mac OS X, and Windows.

diff --git a/html/urls.py b/html/urls.py index d175a3c..0785afe 100644 --- a/html/urls.py +++ b/html/urls.py @@ -27,6 +27,7 @@ # Example: http://example.com/custominstallerbuilder/ # or http://example.com/custominstallerbuilder/ajax/build/ url(r'^$', 'builder_page', name='builder'), + url(r'^fastlane/$', 'fastlane_page', name='fastlane_page'), url(r'^ajax/build/$', 'build_installers', name='ajax-build'), url(r'^ajax/save/$', 'save_state', name='ajax-save'), url(r'^ajax/restore/$', 'restore_state', name='ajax-restore'), diff --git a/html/views.py b/html/views.py index 947b2aa..ff39751 100644 --- a/html/views.py +++ b/html/views.py @@ -128,7 +128,7 @@ def build_installers(request): return ErrorReponse('No build data provided.') build_data = json.loads(request.session['build_string']) - + user_data = {} for user in build_data['users']: @@ -503,6 +503,101 @@ def download_installers_page(request, build_id): +def fastlane_page(request): + """ + + Renders a key and installer download page for a + default user-built seattle build, i.e.: + One vessel, no users, owner name: `default` + + request: + A Django request. + + None. + + If new session + - Creates and stores vesselinfo to appropriate location on disk + - Stores generated key pair to session (memory) + + A Django response. + """ + + fastlane_user_name = u'default' + + try: + if 'build_results' in request.session.keys() and \ + len(request.session['build_results'].values()) > 0 and \ + request.session['build_results'].values()[0].get("fast_lane_build"): + + # The session tells us the user has been here before + # The "fast_lane_build" attribute (set below) distinguishes + # the build_result from one that could have been stored to the session + # by using the interactive CIB + # XXX LP: The other views also verify if the build_id (passed as URLparam) + # is in the session. Does this bring any extra security? I doubt it. + + # There is no need to build again, let's serve what's already there + build_result = request.session['build_results'].values()[0] + build_id = build_result.get('build_id') + keys_downloaded = build_result.get('keys_downloaded', dict()) + + # The manager helps us to find the files stored to disk + manager = BuildManager(build_id=build_id) + installer_links = manager.get_urls() + + else: + # The user is here for the first time + # Create basic installation setup (1 owner, 1 vessel, no users) + users = { + fastlane_user_name: {u'public_key': None} + } + vessels = [ + { + u'owner': fastlane_user_name, + u'percentage': 80, + u'users': [] + } + ] + + # Use build manager to create and store vesselinfo + # and create cryptographic key pair (only stored in memory) + manager = BuildManager(vessel_list=vessels, user_data=users) + build_results = manager.prepare() + + # These are needed in the HTML template to render the proper links + # to the keys and installer + build_id = manager.build_id + installer_links = manager.get_urls() + + # Used in template to display check marks next to buttons + # The keys are new so they cannot have been downloaded + keys_downloaded = False + + build_results["fast_lane_build"] = True + + # download_installer/download_keys views get the build_results + # from the session to serve the correct files + request.session['build_results'] = { + build_id: build_results, + } + request.session.save() + + except: + log_exception(request) + return ErrorResponse('Unknown error occured while' + \ + ' trying to build the installers.') + + return render_to_response('download_installers.html', { + 'fast_lane': True, + 'build_id': build_id, + 'installers': installer_links, + 'keys_downloaded': keys_downloaded, + }, context_instance=RequestContext(request)) + + + + + def error_page(request): """ From 915451fe73e72d87721c7bb50c63ae2e146f01e1 Mon Sep 17 00:00:00 2001 From: Lukas P Date: Tue, 30 Aug 2016 13:58:49 -0400 Subject: [PATCH 3/8] Changes fastlane user to be set in settings, hides breadcrumbs in download view when serving a fast lane build --- html/views.py | 17 +++++++++++------ settings_base.py | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/html/views.py b/html/views.py index ff39751..2f2b710 100644 --- a/html/views.py +++ b/html/views.py @@ -487,7 +487,11 @@ def download_installers_page(request, build_id): if build_id in request.session['build_results']: step = 'installers' user_built = True - + + # If we serve a fast_lane_build we don't show the breadcrumbs + if 'fast_lane_build' in request.session['build_results'][build_id]: + step = False + return render_to_response('download_installers.html', { 'build_id': build_id, @@ -508,7 +512,10 @@ def fastlane_page(request): Renders a key and installer download page for a default user-built seattle build, i.e.: - One vessel, no users, owner name: `default` + One 80 per-cent vessel, one owner/user + + Note: + owner/user-name can be set in settings.FASTLANE_USER_NAME request: A Django request. @@ -522,8 +529,6 @@ def fastlane_page(request): A Django response. """ - fastlane_user_name = u'default' - try: if 'build_results' in request.session.keys() and \ len(request.session['build_results'].values()) > 0 and \ @@ -549,11 +554,11 @@ def fastlane_page(request): # The user is here for the first time # Create basic installation setup (1 owner, 1 vessel, no users) users = { - fastlane_user_name: {u'public_key': None} + settings.FASTLANE_USER_NAME: {u'public_key': None} } vessels = [ { - u'owner': fastlane_user_name, + u'owner': settings.FASTLANE_USER_NAME, u'percentage': 80, u'users': [] } diff --git a/settings_base.py b/settings_base.py index 32ba45e..a120ee4 100644 --- a/settings_base.py +++ b/settings_base.py @@ -130,3 +130,5 @@ # During testing, you may want to use Django's built-in static file server. SERVE_STATIC = False STATIC_BASE = 'static/' + +FASTLANE_USER_NAME = 'user' From 9c1d4bdaa05deaecb02670bcde0198936a32b750 Mon Sep 17 00:00:00 2001 From: Lukas P Date: Tue, 30 Aug 2016 14:28:18 -0400 Subject: [PATCH 4/8] Adds share_url in fastlane --- html/views.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/html/views.py b/html/views.py index 2f2b710..786d72d 100644 --- a/html/views.py +++ b/html/views.py @@ -578,6 +578,10 @@ def fastlane_page(request): # The keys are new so they cannot have been downloaded keys_downloaded = False + # This prevents collision when using interactive CIB and fastlane CIB + # in the same session + # Also hides breadcrumbs when serving "shared" (w/o key links) fastlane + # download page build_results["fast_lane_build"] = True # download_installer/download_keys views get the build_results @@ -592,10 +596,16 @@ def fastlane_page(request): return ErrorResponse('Unknown error occured while' + \ ' trying to build the installers.') + # Builds share_url by using view URLreversing and the request object + share_url = request.build_absolute_uri(reverse('download-installers-page', + args=[build_id])) + + return render_to_response('download_installers.html', { 'fast_lane': True, 'build_id': build_id, 'installers': installer_links, + 'share_url': share_url, 'keys_downloaded': keys_downloaded, }, context_instance=RequestContext(request)) From 6298dc963ce3c9ca161347f2fae0adeb26af0857 Mon Sep 17 00:00:00 2001 From: Lukas P Date: Tue, 30 Aug 2016 15:08:49 -0400 Subject: [PATCH 5/8] Tidies up html/css for share link and QR code (this part also looks nice on small screens now) --- html/static/css/base.css | 4 ++++ html/static/css/download_installers.css | 30 +++++++++++++++---------- html/templates/download_installers.html | 26 ++++++++++++--------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/html/static/css/base.css b/html/static/css/base.css index 129f1ef..f72e531 100644 --- a/html/static/css/base.css +++ b/html/static/css/base.css @@ -241,6 +241,10 @@ button:active, .button:active { display: none; } +.center { + text-align: center; +} + .round_shadow { -webkit-box-shadow: 0 1px 2px #eee; -moz-box-shadow: 0 1px 2px #eee; diff --git a/html/static/css/download_installers.css b/html/static/css/download_installers.css index 5c6d3d9..b4b52e3 100644 --- a/html/static/css/download_installers.css +++ b/html/static/css/download_installers.css @@ -13,27 +13,33 @@ Installer Builder. *****************************************************************/ -#url { - margin: 2em 0 2em 5%; -} -#url span { - border: 1px solid #f7e7ad; - - background-color: #fdf3d0; - margin: 0.4em; + +.share-url { + display: inline-block; padding: 0.4em; - + margin: 0.4em; + + background-color: #fdf3d0; + text-decoration: none; + + border: 1px solid #f7e7ad; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + + /* Break line on small screen */ + overflow-wrap: break-word; + word-wrap: break-word; + -ms-word-break: break-all; + word-break: break-all; } -#url a { - text-decoration: none; - color: inherit; +#qrcode img { + margin: 2em auto; } + table#downloads { margin-left: 5%; diff --git a/html/templates/download_installers.html b/html/templates/download_installers.html index 0a91b85..a73df6a 100644 --- a/html/templates/download_installers.html +++ b/html/templates/download_installers.html @@ -15,11 +15,13 @@ {% block content %} {% comment %} -
+
{% if user_built %}

Your installers are ready!

Bookmark this page to come back later, or share this URL with others:

-
{{ share_url }} Right click on the URL to copy the address.
+
+ {{ share_url }} + Right click on the URL to copy the address.
{% else %}

Thanks for contributing!

The installers below have been customized by a Seattle user. By running these installers, 10% of your computing resources will be donated to an experiment being run by that user.

@@ -27,15 +29,17 @@

Thanks for contributing!

{% endcomment %} -
-
{{ share_url }} Right-click on the URL to copy the address, or scan the QR code below.

-

+
+ +
Right-click on the URL to copy the address, or scan the QR code below.
+
+
From a5e34da4b8e08db71d906494e3d18d60d4054c40 Mon Sep 17 00:00:00 2001 From: Lukas P Date: Tue, 30 Aug 2016 17:37:49 -0400 Subject: [PATCH 6/8] Adds check to allow for concurrent fastlane and non-fastlane build session --- html/views.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/html/views.py b/html/views.py index 786d72d..f7d72a9 100644 --- a/html/views.py +++ b/html/views.py @@ -530,19 +530,23 @@ def fastlane_page(request): """ try: - if 'build_results' in request.session.keys() and \ - len(request.session['build_results'].values()) > 0 and \ - request.session['build_results'].values()[0].get("fast_lane_build"): + build_result = False + + # We have to check if the user already has a build result in his session + # and make sure it's a fastlane build, i.e. + # it does not collide with a build from the interactive CIB + if 'build_results' in request.session.keys(): + for val in request.session['build_results'].values(): + if isinstance(val, dict) and val.get("fast_lane_build"): + build_result = val + break + else: + # This dict will only be saved if the build succeeds + request.session['build_result'] = {} - # The session tells us the user has been here before - # The "fast_lane_build" attribute (set below) distinguishes - # the build_result from one that could have been stored to the session - # by using the interactive CIB - # XXX LP: The other views also verify if the build_id (passed as URLparam) - # is in the session. Does this bring any extra security? I doubt it. + if build_result: # There is no need to build again, let's serve what's already there - build_result = request.session['build_results'].values()[0] build_id = build_result.get('build_id') keys_downloaded = build_result.get('keys_downloaded', dict()) @@ -580,15 +584,13 @@ def fastlane_page(request): # This prevents collision when using interactive CIB and fastlane CIB # in the same session - # Also hides breadcrumbs when serving "shared" (w/o key links) fastlane + # also hides breadcrumbs when serving shared (w/o key links) fastlane # download page build_results["fast_lane_build"] = True - # download_installer/download_keys views get the build_results + # download_installer and download_keys views get the build_results # from the session to serve the correct files - request.session['build_results'] = { - build_id: build_results, - } + request.session['build_results'][build_id] = build_results request.session.save() except: From cc92723e22c160533d942052aa50b1ffba9114e5 Mon Sep 17 00:00:00 2001 From: Lukas P Date: Wed, 31 Aug 2016 11:35:15 -0400 Subject: [PATCH 7/8] Fixes missing dict bug --- html/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/views.py b/html/views.py index f7d72a9..b025ec2 100644 --- a/html/views.py +++ b/html/views.py @@ -542,7 +542,7 @@ def fastlane_page(request): break else: # This dict will only be saved if the build succeeds - request.session['build_result'] = {} + request.session['build_results'] = {} if build_result: From c52912f1971c3bf18f644b39ce7fe1831979a3e0 Mon Sep 17 00:00:00 2001 From: Lukas P Date: Wed, 31 Aug 2016 11:58:24 -0400 Subject: [PATCH 8/8] Refactors name for better distinctiveness --- html/views.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/html/views.py b/html/views.py index b025ec2..99bfc47 100644 --- a/html/views.py +++ b/html/views.py @@ -530,7 +530,7 @@ def fastlane_page(request): """ try: - build_result = False + existing_build_result = False # We have to check if the user already has a build result in his session # and make sure it's a fastlane build, i.e. @@ -538,17 +538,17 @@ def fastlane_page(request): if 'build_results' in request.session.keys(): for val in request.session['build_results'].values(): if isinstance(val, dict) and val.get("fast_lane_build"): - build_result = val + existing_build_result = val break else: # This dict will only be saved if the build succeeds request.session['build_results'] = {} - if build_result: + if existing_build_result: # There is no need to build again, let's serve what's already there - build_id = build_result.get('build_id') - keys_downloaded = build_result.get('keys_downloaded', dict()) + build_id = existing_build_result.get('build_id') + keys_downloaded = existing_build_result.get('keys_downloaded', dict()) # The manager helps us to find the files stored to disk manager = BuildManager(build_id=build_id) @@ -571,7 +571,7 @@ def fastlane_page(request): # Use build manager to create and store vesselinfo # and create cryptographic key pair (only stored in memory) manager = BuildManager(vessel_list=vessels, user_data=users) - build_results = manager.prepare() + new_fastlane_build_results = manager.prepare() # These are needed in the HTML template to render the proper links # to the keys and installer @@ -586,11 +586,11 @@ def fastlane_page(request): # in the same session # also hides breadcrumbs when serving shared (w/o key links) fastlane # download page - build_results["fast_lane_build"] = True + new_fastlane_build_results["fast_lane_build"] = True # download_installer and download_keys views get the build_results # from the session to serve the correct files - request.session['build_results'][build_id] = build_results + request.session['build_results'][build_id] = new_fastlane_build_results request.session.save() except: