faster stats, rearranged layout, direnv instructions in readme, fullscreen toggle

parent a0db4bac
......@@ -21,3 +21,4 @@ build/
code.json
codeclimate.json
static/
.direnv
......@@ -22,10 +22,11 @@ Linux or MacOS capable of running Python3 and git.
# Software Requirements
Download and install git and python3 to get started:
Download and install below system requirements to get started:
- [git](https://git-scm.com/downloads) (download and install)
- [python3](https://www.python.org/downloads/) (download and install)
- [direnv](https://direnv.net/) (download and install, the follow setup instructions)
After installation of above tools, all following steps use the command line:
......@@ -39,6 +40,7 @@ In a directory of your choosing:
git clone --recursive https://github.com/failmap/admin/ # downloads the software
cd admin # enter the directory of the downloaded software
direnv allow # sets Debug to true in this folder. Do not change the settings.py file.
# Quickstart
......
......@@ -444,7 +444,7 @@ def rate_timeline(timeline, url):
if 'tls_qualys_scan' in these_ratings.keys():
if 'tls_qualys_scan' not in given_ratings[label]:
score, json = tls_qualys_rating_based_on_scan(these_ratings['tls_qualys_scan'])
jsons.append(json)
jsons.append(json) if json else ""
scores.append(score)
given_ratings[label].append('tls_qualys_scan')
else:
......@@ -458,7 +458,7 @@ def rate_timeline(timeline, url):
if 'Strict-Transport-Security' not in given_ratings[label]:
score, json = security_headers_rating_based_on_scan(
these_ratings['Strict-Transport-Security'], 'Strict-Transport-Security')
jsons.append(json)
jsons.append(json) if json else ""
scores.append(score)
given_ratings[label].append('Strict-Transport-Security')
else:
......@@ -472,7 +472,7 @@ def rate_timeline(timeline, url):
if 'X-Frame-Options' not in given_ratings[label]:
score, json = security_headers_rating_based_on_scan(
these_ratings['X-Frame-Options'], 'X-Frame-Options')
jsons.append(json)
jsons.append(json) if json else ""
scores.append(score)
given_ratings[label].append('X-Frame-Options')
else:
......@@ -486,7 +486,7 @@ def rate_timeline(timeline, url):
if 'X-XSS-Protection' not in given_ratings[label]:
score, json = security_headers_rating_based_on_scan(
these_ratings['X-XSS-Protection'], 'X-XSS-Protection')
jsons.append(json)
jsons.append(json) if json else ""
scores.append(score)
given_ratings[label].append('X-XSS-Protection')
else:
......@@ -500,7 +500,7 @@ def rate_timeline(timeline, url):
if 'X-Content-Type-Options' not in given_ratings[label]:
score, json = security_headers_rating_based_on_scan(
these_ratings['X-Content-Type-Options'], 'X-Content-Type-Options')
jsons.append(json)
jsons.append(json) if json else ""
scores.append(score)
given_ratings[label].append('X-Content-Type-Options')
else:
......@@ -513,7 +513,7 @@ def rate_timeline(timeline, url):
if 'plain_https' in these_ratings.keys():
if 'plain_https' not in given_ratings[label]:
score, json = http_plain_rating_based_on_scan(these_ratings['plain_https'])
jsons.append(json)
jsons.append(json) if json else ""
scores.append(score)
given_ratings[label].append('plain_https')
else:
......@@ -534,6 +534,9 @@ def rate_timeline(timeline, url):
}""".strip()
# this makes the whole operation a bit slower, but more readable, which matters.
# is also verified json. That also helps.
# print(jsons)
# print(",".join(jsons))
unsorted = xjson.loads("[" + ",".join(jsons) + "]")
l = sorted(unsorted, key=lambda k: int(k["rating"].get("points", 0)), reverse=True)
l = xjson.dumps(obj=l, indent=4) # without correct indent, you'll get single quotes...
......@@ -544,7 +547,7 @@ def rate_timeline(timeline, url):
# print("l")
# print(l)
# print("z")
# print(",".join(jsons))
#
endpoint_jsons.append(endpoint_template % (endpoint.ip,
endpoint.port,
......
......@@ -85,19 +85,19 @@ Todo: better separation of UI and data. The JS messes things up.
/* bootstrap fixed menu terribleness... always overlaps content. */
body {
padding-top: 70px;
padding-top: 50px;
}
@media screen and (max-width: 768px) {
body { padding-top: 0px; }
body { padding-top: 50px; }
}
/* https://github.com/twbs/bootstrap/issues/1768 */
.jumptonav {
display: block;
content: " ";
margin-top: -75px;
height: 75px;
margin-top: -55px;
height: 55px;
visibility: hidden;
}
......@@ -400,4 +400,10 @@ body {
font-size: 30px;
color: silver;
font-family: consolas;
}
\ No newline at end of file
}
.navbar-default {
background-image: linear-gradient(to bottom,rgba(255,255,255,0.9) 0,rgba(255,255,255,0.8) 100%) !important;
backdrop-filter: blur(10px);
background-color: transparent !important;
}
......@@ -47,6 +47,7 @@ var failmap = {
geojson: "",
internetadresses: L.control(),
fullscreenreport: L.control(),
fullscreenhint: L.control(),
dataslider: L.control(),
info: L.control(),
legend: L.control({position: 'bottomright'}),
......@@ -77,6 +78,7 @@ var failmap = {
}
});
this.add_fullscreen_hint();
this.add_dataslider();
this.add_info();
this.add_internetadresses();
......@@ -160,6 +162,19 @@ var failmap = {
this.info.addTo(this.map);
},
add_fullscreen_hint: function () {
this.fullscreenhint.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info');
html = " <div id=\"fullscreen\">" +
" <span class='btn btn-success btn-lg btn-block' v-on:click='toggleFullScreen()'>{{fullscreen}}</span>" +
"</div>";
this._div.innerHTML = html;
return this._div;
};
this.fullscreenhint.addTo(this.map);
},
add_dataslider: function () {
this.dataslider.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info');
......@@ -667,6 +682,23 @@ $(document).ready(function () {
}
});
window.vueFullscreen = new Vue({
el: '#fullscreen',
data: {
fullscreen: "View Full Screen"
},
methods: {
toggleFullScreen: function () {
failmap.map.toggleFullscreen(failmap.map.options)
if (vueFullscreen.fullscreen == "View Full Screen"){
vueFullscreen.fullscreen = "Exit Full Screen"
} else {
vueFullscreen.fullscreen = "View Full Screen"
}
}
}
});
window.vueTopfail = new Vue({
el: '#topfail',
......
......@@ -36,9 +36,9 @@
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="#map">{% trans "Map" %}</a></li>
<li><a href="#bar">{% trans "Bar" %}</a></li>
<li><a href="#intro">{% trans "Introduction" %}</a></li>
<li><a href="#numbers">{% trans "Numbers" %}</a></li>
<li><a href="#bar">{% trans "Bar" %}</a></li>
<li><a href="#topfail">{% trans "Top Fail" %}</a></li>
<li><a href="#explanation">{% trans "Explanation" %}</a></li>
</ul>
......@@ -46,9 +46,12 @@
</div>
</nav>
<div id='map'></div>
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<a name="intro" class="jumptonav"></a>
<h1>{% trans "Fail Map" %}</h1>
<p>{% trans "Fail Map Introduction" %}</p>
<p>Stuur nieuwe subdomeinen in via twitter:
......@@ -61,14 +64,6 @@
{% include "map/donation_row.html" %}
<div class="page-header">
<a name="map" class="jumptonav"></a>
<h1>{% trans "The Map" %}</h1>
<p>{% trans "The Map Introduction" %}</p>
<div id='map'></div>
</div>
<div id="statistics">
<div class="page-header">
<a name="bar" class="jumptonav"></a>
......
......@@ -418,7 +418,7 @@ def stats_determine_when(stat, weeks_back=0):
return when
@cache_page(cache_time)
# @cache_page(cache_time)
def stats(request, weeks_back=0):
# todo: 390 * 7 queries. Still missing the django time dimension type queries.
# Info: the number of urls can be slightly inflated since some organizations share urls
......@@ -447,50 +447,57 @@ def stats(request, weeks_back=0):
'total_urls': 0, 'red_urls': 0, 'orange_urls': 0, 'green_urls': 0,
'included_organizations': 0}
# todo: this can now be rewritten to be faster.
for o in os:
try:
if stat == 'earliest':
rating = OrganizationRating.objects.filter(organization=o, rating__gt=-1)
rating = rating.earliest('when')
else:
rating = OrganizationRating.objects.filter(
organization=o, when__lte=when, rating__gt=-1)
rating = rating.latest('when')
measurement["total_organizations"] += 1
measurement["total_score"] += rating.rating
if rating.rating < 200:
measurement["green"] += 1
if 199 < rating.rating < 1000:
measurement["orange"] += 1
if rating.rating > 999:
measurement["red"] += 1
# count the urls, from the latest rating. Which is very dirty :)
# it will double the urls that are shared between organizations.
# that is not really bad, it distorts a little.
# we're forced to load each item separately anyway, so why not read it?
x = json.loads(rating.calculation)
measurement["total_urls"] += len(x['organization']['urls'])
measurement["green_urls"] += sum(
[int(l['url']['points']) < 200 for l in x['organization']['urls']])
measurement["orange_urls"] += sum(
[199 < int(l['url']['points']) < 1000 for l in x['organization']['urls']])
measurement["red_urls"] += sum(
[int(l['url']['points']) > 999 for l in x['organization']['urls']])
measurement["included_organizations"] += 1
except OrganizationRating.DoesNotExist:
measurement["total_organizations"] += 1
measurement["total_score"] += 0
measurement["no_rating"] += 1
# if stat == 'earliest':
# rating = OrganizationRating.objects.filter(organization=o, rating__gt=-1)
# rating = rating.earliest('when')
# else:
# rating = OrganizationRating.objects.filter(
# organization=o, when__lte=when, rating__gt=-1)
# rating = rating.latest('when')#
ratings = OrganizationRating.objects.raw("""SELECT * FROM
map_organizationrating
INNER JOIN
(SELECT MAX(id) as id2 FROM map_organizationrating or2
WHERE `when` <= '%s' GROUP BY organization_id) as x
ON x.id2 = map_organizationrating.id""" % when)
for rating in ratings:
measurement["total_organizations"] += 1
measurement["total_score"] += rating.rating
if rating.rating < 200:
measurement["green"] += 1
if 199 < rating.rating < 1000:
measurement["orange"] += 1
if rating.rating > 999:
measurement["red"] += 1
# count the urls, from the latest rating. Which is very dirty :)
# it will double the urls that are shared between organizations.
# that is not really bad, it distorts a little.
# we're forced to load each item separately anyway, so why not read it?
x = json.loads(rating.calculation)
measurement["total_urls"] += len(x['organization']['urls'])
measurement["green_urls"] += sum(
[int(l['url']['points']) < 200 for l in x['organization']['urls']])
measurement["orange_urls"] += sum(
[199 < int(l['url']['points']) < 1000 for l in x['organization']['urls']])
measurement["red_urls"] += sum(
[int(l['url']['points']) > 999 for l in x['organization']['urls']])
measurement["included_organizations"] += 1
# todo: add all non-existing organizations at this point:
#
""" measurement["total_organizations"] += 1
measurement["total_score"] += 0
measurement["no_rating"] += 1
"""
if measurement["included_organizations"]:
measurement["red percentage"] = round((measurement["red"] /
......
......@@ -53,13 +53,14 @@ def develop_timeline():
# has ratings on a ton of redundant endpoints.
url = Url.objects.all().filter(url='webmail.zaltbommel.nl').get()
url = Url.objects.all().filter(url='geo.aaenhunze.nl').get()
url = Url.objects.all().filter(url='webserver03.bloemendaal.nl').get()
data = timeline(url=url)
show_timeline_console(data, url)
rerate_url_with_timeline(url)
OrganizationRating.objects.all().delete()
for organization in url.organization.all():
rate_organization_efficient(organization=organization, create_history=True)
# OrganizationRating.objects.all().delete()
# for organization in url.organization.all():
# rate_organization_efficient(organization=organization, create_history=True)
def develop_sslscan():
......
......@@ -396,4 +396,4 @@ if not DEBUG:
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE
COMPRESS_OFFLINE = True # defaults to false
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_ENABLED
# Enabled when debug is off by default.
\ No newline at end of file
# Enabled when debug is off by default.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment