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 35 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ nosetests.xml

# Functional test logs
**/ghostdriver.log

.vagrant
.chroot
68 changes: 64 additions & 4 deletions HACKING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,66 @@
# Contact
# The SecureDrop Development Community

Mailing List: [email protected]
IRC: #securedrop-dev on OFTC
You can subscribe to our mailing list here: [securedrop-dev](https://lists.riseup.net/www/subscribe/securedrop-dev). Or join is in #securedrop-dev on [irc.oftc.net](http://www.oftc.net/).

# Hacking on the Code

The SecureDrop production environment runs Ubuntu precise. In order to make it so all developers have as similar an environment as possible, we have made it easy to write and test code changes in precise, even if that's not the operating system you're running.

The two ways to do this are using Vagrant or using a chroot jail. Vagrant works by creating an Ubuntu precise VM using VirtualBox and installing a development environment inside of it. Vagrant and VirtualBox are cross-platform, which means this method works in GNU/Linux, OS X, and Windows. However, it won't work if your development environment is already a VM, like if you run Qubes. It also might not work if you're using old hardware that doesn't support 64-bit virtualization. If you can't use Vagrant, you can use a chroot jail instead. Using a chroot jail only works if you're already running GNU/Linux.

## Vagrant and VirtualBox

Install [Vagrant](http://vagrantup.com) and [VirtualBox](http://www.virtualbox.org), clone the git repository, and start vagrant:

git clone https://github.com/freedomofpress/securedrop.git
cd securedrop
vagrant up

This creates a virtual machine with the SecureDrop codebase in /vagrant. You can edit files on your host machine in your favorite editor, and restart the web servers in the VM to test your changes.

You can ssh into the VM by typing `vagrant ssh`.

SecureDrop consists of two related web applications, one for sources and one for journalists. You can start the web servers from within the VM with:

cd /vagrant/securedrop
python source.py &
python journalist.py &

Now you can visit SecureDrop by loading [http://localhost:8080] for the source interface and [http://localhost:8081] for the journalist interface in your web browser.

To run tests:

cd /vagrant/securedrop
./test.sh

For more instructions on how to interact with your VM, refer to the [Vagrant website](http://vagrantup.com).

## Chroot Jail

First install the appropriate dependencies for your VM's OS:

sudo apt-get install debootstrap schroot
sudo yum install debootstrap schroot

You can use the script chroot-dev to setup and use your development environment.

git clone https://github.com/freedomofpress/securedrop.git
cd securedrop
./chroot-dev

This will show you a list of commands:

Usage: ./chroot-dev [command]

up # create chroot if needed, mount filesystems, start servers
down # stop servers, unmount filesystems from chroot
start # start securedrop web app servers
stop # stop securedrop web app servers
restart # restart securedrop web app servers
test # run tests
destroy # destroy chroot jail

All you need to do is run `./chroot-dev up`. The first time you do this it will take some time to install and configure your chroot development environment. In the future, all you have to do is run `./chroot-dev up` and you'll be ready to start working.

You can run tests with `./chroot-dev test`.

If you want to hack on the web application, check out [securedrop/HACKING.md](/securedrop/HACKING.md).
165 changes: 165 additions & 0 deletions chroot-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#!/bin/bash

if [[ $EUID -eq 0 ]]; then
echo "Please run this as your normal user, not root"
exit 1
fi
if ! hash debootstrap 2>/dev/null; then
echo "Install debootstrap before continuing"
exit 1
fi
if ! hash schroot 2>/dev/null; then
echo "Install schroot before continuing"
exit 1
fi

SOURCE_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
CHROOT_DIR=$SOURCE_ROOT/.chroot

usage() {
cat <<EOS
Usage: ./chroot-dev [command]

up # create chroot if needed, mount filesystems, start servers
down # stop servers, unmount filesystems from chroot
start # start securedrop web app servers
stop # stop securedrop web app servers
restart # restart securedrop web app servers
test # run tests
clean # recreate db, keys, and everything else
destroy # destroy chroot jail

EOS
}

check_chroot() {
if [ -d "$CHROOT_DIR" ]; then
chroot_exists=1
else
chroot_exists=0
fi
}

require_chroot() {
check_chroot
if [ $chroot_exists -eq 0 ]; then
echo 'You must run "chroot-dev up" first to create a chroot jail'
exit 0
fi
}

mount_filesystems() {
sudo mount proc $CHROOT_DIR/proc -t proc
sudo mount sys $CHROOT_DIR/sys -t sysfs
sudo mount --bind /dev $CHROOT_DIR/dev
sudo mount $SOURCE_ROOT $CHROOT_DIR/securedrop -o bind
}

unmount_filesystems() {
sudo umount -l $CHROOT_DIR/securedrop
sudo umount -l $CHROOT_DIR/dev
sudo umount -l $CHROOT_DIR/sys
sudo umount -l $CHROOT_DIR/proc
}

start_servers() {
sudo schroot -c securedrop -d /securedrop/securedrop -- sudo -u dev python source.py &
echo Started source server on http://localhost:8080/
sudo schroot -c securedrop -d /securedrop/securedrop -- sudo -u dev python journalist.py &
echo Started document server on http://localhost:8081/
}

stop_servers() {
sudo schroot -c securedrop -d / -- killall python
echo Stopped SecureDrop servers
}

# patch schroot.conf, if needed
if ! grep -q "\[securedrop\]" /etc/schroot/schroot.conf; then
sudo sh -c "cat $SOURCE_ROOT/dev_files/schroot.conf | sed 's|SECUREDROP_LOCATION|$CHROOT_DIR|g' >> /etc/schroot/schroot.conf"
fi

# commands
if [ "$#" -ne 1 ]; then
usage
exit 0
fi
CMD=$1

# up
if [ $CMD == "up" ]; then
check_chroot
if [ $chroot_exists -eq 0 ]; then
echo "Installing Ubuntu 12.04 in chroot environment"
# install precise inside of the chroot
mkdir -p $CHROOT_DIR
sudo debootstrap --keyring $SOURCE_ROOT/dev_files/ubuntu-archive-keyring.gpg --arch=amd64 precise $CHROOT_DIR http://archive.ubuntu.com/ubuntu/
sudo mkdir -p $CHROOT_DIR/securedrop
sudo cp $SOURCE_ROOT/dev_files/sources.list $CHROOT_DIR/etc/apt/sources.list
sudo cp /etc/resolv.conf $CHROOT_DIR/etc/resolv.conf
sudo sh -c "echo '127.0.0.1 dev' >> $CHROOT_DIR/etc/hosts"

# setup securedrop dev environment
mount_filesystems
sudo schroot -c securedrop -d / -- apt-get update
sudo schroot -c securedrop -d / -- apt-get -y install wget build-essential psmisc
sudo schroot -c securedrop -d / -- adduser --uid $EUID --system --disabled-login dev
sudo schroot -c securedrop -d /securedrop -- ./setup_dev.sh -r /home/dev/.securedrop -u
sudo schroot -c securedrop -d / -- chown -R dev /home/dev/.securedrop
sudo schroot -c securedrop -d / -- chown -R dev /securedrop/securedrop
else
mount_filesystems
fi

start_servers

# down
elif [ $CMD == "down" ]; then
require_chroot
stop_servers
unmount_filesystems

# start
elif [ $CMD == "start" ]; then
require_chroot
start_servers

# stop
elif [ $CMD == "stop" ]; then
require_chroot
stop_servers

# restart
elif [ $CMD == "restart" ]; then
require_chroot
stop_servers
start_servers

# test
elif [ $CMD == "test" ]; then
require_chroot
sudo schroot -c securedrop -d /securedrop/securedrop -- sudo -u dev ./test.sh

# clean
elif [ $CMD == "clean" ]; then
require_chroot
stop_servers
sudo schroot -c securedrop -d / -- rm -rf /home/dev/.securedrop
sudo schroot -c securedrop -d / -- sudo -u dev mkdir -p /home/dev/.securedrop/keys
sudo schroot -c securedrop -d / -- sudo -u dev chmod 700 /home/dev/.securedrop/keys
sudo schroot -c securedrop -d / -- sudo -u dev gpg --homedir /home/dev/.securedrop/keys --import /securedrop/securedrop/test_journalist_key.sec
sudo schroot -c securedrop -d /securedrop/securedrop -- sudo -u dev python -c "import db; db.init_db()"
start_servers

# destroy
elif [ $CMD == "destroy" ]; then
require_chroot
stop_servers
unmount_filesystems
sudo rm -rf $CHROOT_DIR

else
usage
exit 0
fi

4 changes: 4 additions & 0 deletions dev_files/schroot.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

[securedrop]
description=SecureDrop chroot
directory=SECUREDROP_LOCATION
4 changes: 4 additions & 0 deletions dev_files/sources.list
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
deb http://archive.ubuntu.com/ubuntu precise main universe
deb-src http://archive.ubuntu.com/ubuntu precise main universe


Binary file added dev_files/ubuntu-archive-keyring.gpg
Binary file not shown.
26 changes: 0 additions & 26 deletions securedrop/HACKING.md

This file was deleted.

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

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 @@ -143,7 +144,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
Loading