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

UI refresh #382

Merged
merged 29 commits into from
May 24, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
917a4ca
Merge branch 'better-filenames' into better-filenames-chroot
micahflee Apr 29, 2014
cf83481
Merge branch 'chroot' into better-filenames-chroot
micahflee Apr 29, 2014
eaec284
fancy python simplification of journalist_filename (#349)
micahflee Apr 29, 2014
7029a45
DRYed up filename tests, and use raw strings for regex
micahflee Apr 29, 2014
270f66d
starting to implement new UI (#329). made new source homepage, and ma…
micahflee Apr 30, 2014
0ff78b7
remade source template's base.html, and updated UI for /generate (#329)
micahflee Apr 30, 2014
3715e81
built UI for /lookup, and made notifications look modern (#329)
micahflee May 9, 2014
cbd7d3d
fixed some css after testing in tor browser (#329)
micahflee May 13, 2014
5311926
fixed test_create (#329)
micahflee May 16, 2014
afeddb9
fixed test_generate
micahflee May 16, 2014
338579c
fixed test_submit_and_retrieve_happy_path test (#329)
micahflee May 23, 2014
9da00f8
fixed source_navigation_steps tests
micahflee May 23, 2014
7d58503
added new styling to journalist interface
cwattrus May 23, 2014
3ab1061
added changes to col.html that got deleted... somehow...
cwattrus May 23, 2014
057871d
Merge branch 'cwattrus-ui-refresh' into ui-refresh
micahflee May 23, 2014
a71ff1b
fixing up css for the journalist interface
micahflee May 23, 2014
d45ec2d
deleted old, unused css file
micahflee May 23, 2014
0ba94c7
update notifications in journalist interface
micahflee May 23, 2014
ea58f9f
added util.py for formatting dates
micahflee May 23, 2014
2662268
journalist replies look good now
micahflee May 23, 2014
3dfdf31
fix test_reply_normal test
micahflee May 24, 2014
e07d5e2
Merge branch 'develop' into ui-refresh
micahflee May 24, 2014
0510bdc
added back custom header support
micahflee May 24, 2014
7fde4c5
minor journalist interface improvements
micahflee May 24, 2014
662a326
oops, should not have commited the TI logo
micahflee May 24, 2014
b7025f3
added comment to describe what banner warning flash messages are
micahflee May 24, 2014
fed9a41
changed selected="" to just selected (#382)
micahflee May 24, 2014
005bff0
4-space indents instead of 2-space indents
micahflee May 24, 2014
ef474c1
Merge branch 'develop' into ui-refresh
micahflee May 24, 2014
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
5 changes: 3 additions & 2 deletions securedrop/journalist.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import crypto_util
import store
import background
import util
from db import db_session, Source, Submission

app = Flask(__name__, template_folder=config.JOURNALIST_TEMPLATES_DIR)
Expand All @@ -25,7 +26,7 @@
app.jinja_env.globals['header_image'] = config.CUSTOM_HEADER_IMAGE
app.jinja_env.globals['use_custom_header_image'] = True
else:
app.jinja_env.globals['header_image'] = 'securedrop.png'
app.jinja_env.globals['header_image'] = 'logo.png'
app.jinja_env.globals['use_custom_header_image'] = False

@app.teardown_appcontext
Expand Down Expand Up @@ -151,7 +152,7 @@ def reply():

crypto_util.encrypt(crypto_util.getkey(g.sid), msg, output=
store.path(g.sid, filename))

db_session.commit()
return render_template('reply.html', sid=g.sid,
codename=g.source.journalist_designation)
Expand Down
29 changes: 19 additions & 10 deletions securedrop/journalist_templates/base.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' href='/static/css/securedrop.css' type='text/css' media='all' />
<link rel="icon" type="image/png" href="/static/i/favicon.png">
<title>SecureDrop</title>
<link rel="stylesheet" href="/static/css/normalize.css" type="text/css" media="all" />
<link rel="stylesheet" href="/static/css/styles.css" type="text/css" media="all" />
<link rel="stylesheet" href="/static/css/font-awesome.css" type="text/css" media="all" />
<link rel="icon" type="image/png" href="/static/i/favicon.png">
<script src="/static/js/libs/jquery-2.1.1.min.js"></script>
<script src="/static/js/libs/localForage.js"></script>
<script src="/static/js/journalist.js"></script>
{% block extrahead %}{% endblock %}
</head>
<body>
<div id="wrapper">
<div class="content">
{% block header %}
<div id="header">
<a href="/"><img src="/static/i/{{ header_image }}" alt="SecureDrop"></a>
<a href="/"><img src="/static/i/{{ header_image }}" class="logo small" alt="SecureDrop"></a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: should the alt message be "SecureDrop", or the name of org? That can be a follow-up (or we can just not bother).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't know the name of org. :( Perhaps we will someday, when #344 is done.

{% if use_custom_header_image %}
<div class="powered">Powered by <img src="/static/i/securedrop_small.png" alt="SecureDrop"></div>
<div class="powered">
Powered by<br/>
<img src="/static/i/securedrop_small.png" alt="SecureDrop">
</div>
{% endif %}
</div>
{% endblock %}

{% include 'flashed.html' %}
{% block body %}{% endblock %}
<div class="panel selected">
<hr class="no-line" />
{% include 'flashed.html' %}

{% block body %}{% endblock %}
</div>

{% block footer %}
<div id="footer">
Like all software, SecureDrop may contain security bugs. Use at your own risk.<br/>
<footer>
Powered by <em>SecureDrop {{ version }}</em>.
</div>
</footer>
{% endblock %}
</div>
</body>
Expand Down
12 changes: 6 additions & 6 deletions securedrop/journalist_templates/col.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ <h2><span class="headline">Read documents</span></h2>
<h3>Collection from: <span class="code-name">{{ codename }}</span></h3>
<form action='/regenerate-code' method='post'>
<input name="csrf_token" type="hidden" value="{{ csrf_token() }}"/>
<input type='hidden' name='sid' value='{{ sid }}'>
<input type='submit' value='Generate a new codename for this source'>
<input type="hidden" name="sid" value="{{ sid }}">
<input type="submit" value="Generate a new codename for this source" class="btn small">
</form>

{% if docs %}
Expand All @@ -24,13 +24,13 @@ <h3>Collection from: <span class="code-name">{{ codename }}</span></h3>
{% endif %}
</li>
{% endfor %}
</ul>
<input name="csrf_token" type="hidden" value="{{ csrf_token() }}"/>
<input type="hidden" name="sid" value="{{ sid }}" autocomplete="off"/>
<p>
<button type="submit" name="action" value="download">Download selected</button>
<button type="submit" name="action" value="delete">Delete selected</button>
(<span id="select_all">select all</span>, <span id="select_none">select none</span>)</p>
</ul>
<button type="submit" name="action" value="download" class="small">Download selected</button>
<button type="submit" name="action" value="delete" class="small">Delete selected</button>
<span id="select_all" class="select"><i class="fa fa-check-square-o"></i> select all</span> <span id="select_none" class="select"><i class="fa fa-square-o"></i> select none</span></p>
</form>
{% else %}
<p><br />No documents to display.</p>
Expand Down
5 changes: 4 additions & 1 deletion securedrop/journalist_templates/flag.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{% extends "base.html" %}
{% block body %}
<p class="notification">Thanks!</p>
<p class="flash notification">
<i class="fa fa-info-circle pull-left"></i>
Thanks!
</p>

<p>SecureDrop will generate a secure encryption key for this source the next time that they log in. Once the key has been generated, a reply box will appear under their collection of documents. You can use this box to write encrypted replies to them.</p>

Expand Down
11 changes: 10 additions & 1 deletion securedrop/journalist_templates/flashed.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<p class="{{ category }}">{{ message }}</p>
{% if category != 'banner-warning' %}
<p class="flash {{ category }}">
{% if category == 'notification' %}
<i class="fa fa-info-circle pull-left"></i>
{% elif category == 'error' %}
<i class="fa fa-exclamation-triangle pull-left"></i>
{% endif %}
{{ message }}
</p>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
Expand Down
10 changes: 3 additions & 7 deletions securedrop/journalist_templates/index.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{% extends "base.html" %}
{% block body %}
<div id="content" class="journalist-view-all">
<h2><span class="headline">Latest submissions</span></h2>
<h2><span class="headline">Sources</span></h2>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay, this has always irked me!

{% if sources %}
<p>Here are the various collections of documents that have been submitted, with the most recently updated first:</p>
<form id="delete_collections" action="/col/delete" method="post">
<input id='filter' type='text' placeholder='filter by codename' autofocus="autofocus">
<ul id="cols" class="plain">
Expand All @@ -27,11 +26,8 @@ <h2><span class="headline">Latest submissions</span></h2>
</ul>
<input name="csrf_token" type="hidden" value="{{ csrf_token() }}"/>
<p>
<button type="submit" name="action" value="delete">Delete selected</button>
(<span id="select_all">select all</span>, <span id="select_none">select none</span>)
</p>
<p>Click the button above to delete selected collections.
<em>Warning: If you do this, the selected collections of submisisons will be unrecoverable and each corresponding source will no longer be able to login with their previous codename.</em>
<button type="submit" name="action" value="delete" class="small"><i class="fa fa-minus-circle"></i> Delete selected</button>
<span id="select_all" class="select"><i class="fa fa-check-square-o"></i> select all</span> <span id="select_none" class="select"><i class="fa fa-square-o"></i> select none</span>
</p>
</form>
</div>
Expand Down
7 changes: 5 additions & 2 deletions securedrop/journalist_templates/reply.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{% extends "base.html" %}
{% block body %}
<p class="notification">Thanks! Your reply has been stored.</p>
<p class="flash notification">
<i class="fa fa-info-circle pull-left"></i>
Thanks! Your reply has been stored.
</p>

<p>You will now see it in the list of documents in that collection. Once the source has read it, they will be asked to delete it. If it disappears from the list, then you know it has been read.</p>

<p><a href="/col/{{ sid }}">Continue to the list of documents for {{ codename }}...</a></p>
<p><a href="/col/{{ sid }}">Continue to the list of documents for <strong>{{ codename }}</strong>...</a></p>
{% endblock %}
7 changes: 4 additions & 3 deletions securedrop/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import crypto_util
import store
import background
import util
from db import db_session, Source, Submission

app = Flask(__name__, template_folder=config.SOURCE_TEMPLATES_DIR)
Expand Down Expand Up @@ -101,7 +102,7 @@ def check_tor2web():
flash('<strong>WARNING:</strong> You appear to be using Tor2Web. '
'This <strong>does not</strong> provide anonymity. '
'<a href="/tor2web-warning">Why is this dangerous?</a>',
"header-warning")
"banner-warning")


@app.route('/')
Expand Down Expand Up @@ -152,8 +153,8 @@ def lookup():
except UnicodeDecodeError:
app.logger.error("Could not decode reply %s" % fn)
else:
date = str(datetime.fromtimestamp(
os.stat(store.path(g.sid, fn)).st_mtime))
d = datetime.fromtimestamp(os.stat(store.path(g.sid, fn)).st_mtime)
date = util.format_time(d)
replies.append(dict(id=fn, date=date, msg=msg))

def async_genkey(sid, codename):
Expand Down
6 changes: 6 additions & 0 deletions securedrop/source_templates/banner_warning_flashed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{# these are flash messages that appear at the top and are really scary, like if you're using tor2web #}
{% with messages = get_flashed_messages(with_categories=True, category_filter=["banner-warning"]) %}
{% for category, message in messages %}
<p class="flash {{ category }}"><i class="fa fa-exclamation-triangle pull-left"></i> {{ message|safe }}</p>
{% endfor %}
{% endwith %}
38 changes: 22 additions & 16 deletions securedrop/source_templates/base.html
Original file line number Diff line number Diff line change
@@ -1,36 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/css/securedrop.css" type="text/css" media="all" />
<link rel="icon" type="image/png" href="/static/i/favicon.png">
<title>SecureDrop</title>
<title>SecureDrop | Protecting Journalists and Sources</title>
<link rel="stylesheet" href="/static/css/normalize.css" type="text/css" media="all" />
<link rel="stylesheet" href="/static/css/styles.css" type="text/css" media="all" />
<link rel="stylesheet" href="/static/css/font-awesome.css" type="text/css" media="all" />
<link rel="icon" type="image/png" href="/static/i/favicon.png" >
{% block extrahead %}{% endblock %}
</head>
<body>
{% with messages = get_flashed_messages(with_categories=True, category_filter=["header-warning"]) %}
{% for category, message in messages %}
<p class="{{ category }}">{{ message|safe }}</p>
{% endfor %}
{% endwith %}
{% include 'banner_warning_flashed.html' %}

<div id="wrapper">
<div class="content">
{% block header %}
<div id="header">
<a href="/"><img src="/static/i/{{ header_image }}" alt="SecureDrop"></a>
<a href="/"><img src="/static/i/{{ header_image }}" class="logo small" alt="SecureDrop"></a>
{% if use_custom_header_image %}
<div class="powered">Powered by <img src="/static/i/securedrop_small.png" alt="SecureDrop"></div>
<div class="powered">
Powered by<br/>
<img src="/static/i/securedrop_small.png" alt="SecureDrop">
</div>
{% endif %}
</div>
{% endblock %}

{% block body %}{% endblock %}
<div class="panel selected">
<hr class="no-line" />

{% block body %}{% endblock %}

{% block footer %}
<div id="footer">
Like all software, SecureDrop may contain security bugs. Use at your own risk.<br/>
Powered by <em>SecureDrop {{ version }}</em>.
</div>

{% block footer %}
<footer>
Like all software, SecureDrop may contain security bugs. Use at your own risk. Powered by SecureDrop {{ version }}.
</footer>
{% endblock %}
</div>
</body>
</html>

11 changes: 10 additions & 1 deletion securedrop/source_templates/flashed.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<p class="{{ category }}">{{ message }}</p>
{% if category != 'banner-warning' %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment would be nice, either here or in banner_warning_flashed.html, to explain why they're separated like this (because escaping and also layout).

<p class="flash {{ category }}">
{% if category == 'notification' %}
<i class="fa fa-info-circle pull-left"></i>
{% elif category == 'error' %}
<i class="fa fa-exclamation-triangle pull-left"></i>
{% endif %}
{{ message }}
</p>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
Expand Down
51 changes: 30 additions & 21 deletions securedrop/source_templates/generate.html
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
{% extends "base.html" %}

{% block body %}
<div id="content" class="submit-2">
<h2>Submitting for the first time</h2>
<p>To protect your identity, we're assigning you a unique code name.</p>
<p><b>Your code name is:</b></p>
<p id="code-name" class="code-name">{{ codename }}</p>
<div id='regenerate-box'>
Click Generate if you would like to create a different code name.
<h2>Remember this code and keep it secret</h2>
<p class="center">To protect your identity, we're assigning you a unique code name.</p>

<hr class="no-line" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's quirky, but... I like it. This can stay, although I wonder if there is a better way.


<div class="code">
<i class="fa fa-lock pull-left"></i> <strong id="codename">{{ codename }}</strong>
<div class="pull-right">
<form id="regenerate-form" method="post">
<input name="csrf_token" type="hidden" value="{{ csrf_token() }}">
Desired code name length:
<select name="number-words" id="number-words">
<option value="7">7</option>
<option value="8" selected>8</option>
<option value="7">7 words</option>
<option value="8" selected>8 words</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
words.
<input type="submit" id="regenerate-submit" value="Generate">
<button type="submit" id="regenerate-submit" class="small">
<i class="fa fa-refresh"></i>
</button>
</form>
</div>
<p>
It is extremely important that you both remember this code and keep it secret. Memorize the code or write it down, but do not save it on your computer. After submitting documents, you will need to provide this code to log back in and check for responses. Also, this code is the only authentication needed to log in with your account: if you write it down, be sure to keep it hidden.
</p>
<form id="create-form" method="post" action="/create" autocomplete="off">
<input name="csrf_token" type="hidden" value="{{ csrf_token() }}">
<p>
Once you've taken care of that: <button id="continue-button" class="button-custom" type="submit">Continue...</button>
</p>
</form>
</div>

<div class="clearfix"></div>
<hr class="no-line">

<p class="serious">Store this code somewhere safe, or memorize it. It can be used to compromise your anonymity.</p>

<hr class="no-line" />

<p><strong>Next steps:</strong> You will need to provide this code to log back in and check for responses.</p>

<hr class="no-line" />

<form id="create-form" method="post" action="/create" autocomplete="off">
<input name="csrf_token" type="hidden" value="{{ csrf_token() }}">
<button type="submit" class="btn block pull-right" id="continue-button"><i class="fa fa-arrow-circle-o-right"></i> Continue</button>
</form>
{% endblock %}
Loading