Privatley share passwords using redis
This commit is contained in:
parent
b3800a65d6
commit
b555472d0f
15 changed files with 9028 additions and 1 deletions
2
README
2
README
|
@ -1 +1 @@
|
||||||
Redis frontent to securley share passwords
|
Redis frontend to securley share passwords
|
||||||
|
|
0
__init__.py
Normal file
0
__init__.py
Normal file
70
app.py
Normal file
70
app.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import redis
|
||||||
|
|
||||||
|
from flask import abort, Flask, render_template, request
|
||||||
|
|
||||||
|
|
||||||
|
application = Flask(__name__)
|
||||||
|
application.secret_key = os.environ.get('SECRET_KEY', 'Secret Key')
|
||||||
|
application.config.update(dict(STATIC_URL=os.environ.get('STATIC_URL', 'static')))
|
||||||
|
|
||||||
|
id = lambda: uuid.uuid4().get_hex()
|
||||||
|
redis_host = os.environ.get('REDIS_HOST', 'localhost')
|
||||||
|
r = redis.StrictRedis(host=redis_host, port=6379, db=0)
|
||||||
|
|
||||||
|
time_conversion = {
|
||||||
|
'week': 604800,
|
||||||
|
'day': 86400,
|
||||||
|
'hour': 3600
|
||||||
|
}
|
||||||
|
|
||||||
|
def set_password(password, ttl):
|
||||||
|
key = id()
|
||||||
|
r.set(key, password)
|
||||||
|
r.expire(key, ttl)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_password(key):
|
||||||
|
password = r.get(key)
|
||||||
|
r.delete(key)
|
||||||
|
return password
|
||||||
|
|
||||||
|
def clean_input():
|
||||||
|
"""
|
||||||
|
Make sure we're not getting bad data from the front end,
|
||||||
|
format data to be machine readable
|
||||||
|
"""
|
||||||
|
if not 'password' in request.form:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
if not 'ttl' in request.form:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
time_period = request.form['ttl'].lower()
|
||||||
|
if not time_period in time_conversion:
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
return time_conversion[time_period], request.form['password']
|
||||||
|
|
||||||
|
@application.route('/', methods=['GET'])
|
||||||
|
def index():
|
||||||
|
return render_template('set_password.html')
|
||||||
|
|
||||||
|
@application.route('/', methods=['POST'])
|
||||||
|
def handle_password():
|
||||||
|
ttl, password = clean_input()
|
||||||
|
key = set_password(password, ttl)
|
||||||
|
return render_template('confirm.html', password_link=request.url_root+key)
|
||||||
|
|
||||||
|
@application.route('/<password_key>', methods=['GET'])
|
||||||
|
def show_password(password_key):
|
||||||
|
password = get_password(password_key)
|
||||||
|
if not password:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
return render_template('password.html', password=password)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
application.run(host='0.0.0.0', debug=True)
|
1058
static/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
1058
static/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
static/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
9
static/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5774
static/bootstrap/css/bootstrap.css
vendored
Normal file
5774
static/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
static/bootstrap/css/bootstrap.min.css
vendored
Normal file
9
static/bootstrap/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
static/bootstrap/img/glyphicons-halflings-white.png
Normal file
BIN
static/bootstrap/img/glyphicons-halflings-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
BIN
static/bootstrap/img/glyphicons-halflings.png
Normal file
BIN
static/bootstrap/img/glyphicons-halflings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
2027
static/bootstrap/js/bootstrap.js
vendored
Normal file
2027
static/bootstrap/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
6
static/bootstrap/js/bootstrap.min.js
vendored
Normal file
6
static/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26
templates/base.html
Normal file
26
templates/base.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Send Password</title>
|
||||||
|
<link href="{{ config.STATIC_URL }}/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container">
|
||||||
|
<a class="brand" href="/">Send Password</a>
|
||||||
|
<div class="nav-collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li class="active"><a href="/">Share</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||||
|
<script src="{{ config.STATIC_URL }}/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
{% block js %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
10
templates/confirm.html
Normal file
10
templates/confirm.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<section>
|
||||||
|
<div class="page-header"><h1>Password stored!</h1></div>
|
||||||
|
<h4>{{ password_link }}</h4>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
11
templates/password.html
Normal file
11
templates/password.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<section>
|
||||||
|
<div class="page-header"><h1>Here is your password!</h1></div>
|
||||||
|
<h4>{{ password }}</h4>
|
||||||
|
<p>Remember to copy this password! Its been deleted from the database and can't be re-accessed.</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
27
templates/set_password.html
Normal file
27
templates/set_password.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<section>
|
||||||
|
<div class="page-header"><h1>Password Share</h1></div>
|
||||||
|
<form class="form-horizontal" id="password_create" method="post">
|
||||||
|
<input type="text" id="password" name="password" autofocus="True" placeholder="Share a Password">
|
||||||
|
<select name="ttl">
|
||||||
|
<option>Week</option>
|
||||||
|
<option>Day</option>
|
||||||
|
<option>Hour</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-primary" id="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
<h3>Using this tool</h3>
|
||||||
|
<p>This tool allows us to share passwords in a secure way. Submit a password
|
||||||
|
and a time to live. The password will be stored as long as time to live
|
||||||
|
(default one week). The password can only be read once. Once somebody
|
||||||
|
reads the password it is automatically removed from the system.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{% endblock %}
|
Loading…
Reference in a new issue