fifth commit

This commit is contained in:
iou1name 2019-09-20 19:24:12 -04:00
parent 6acc767923
commit 325d2af09c
6 changed files with 163 additions and 22 deletions

View File

@ -6,6 +6,7 @@ import json
import secrets import secrets
import functools import functools
from datetime import datetime from datetime import datetime
from collections import defaultdict
from aiohttp import web from aiohttp import web
import jinja2 import jinja2
@ -37,14 +38,17 @@ def auth_required(func):
if not sid or not user_id: if not sid or not user_id:
raise web.HTTPFound(location=login_url) raise web.HTTPFound(location=login_url)
async with request.app['pool'].acquire() as conn: async with request.app['pool'].acquire() as conn:
sessions = await conn.fetch( session = await conn.fetchrow(
"SELECT * FROM user_session " "SELECT user_info.id, user_info.username, user_info.admin, "
"WHERE user_id = $1 AND expires > NOW()", "user_session.last_used "
user_id) "FROM user_info LEFT JOIN user_session "
session = [s for s in sessions if s.get('id') == sid] "ON (user_info.id = user_session.user_id) "
"WHERE user_info.id = $1 AND user_session.id = $2 "
"AND user_session.expires > NOW()",
user_id, sid)
if session: if session:
request['session'] = dict(session)
resp = await func(request, *args, **kwargs) resp = await func(request, *args, **kwargs)
session = session[0]
tz = session['last_used'].tzinfo tz = session['last_used'].tzinfo
delta = datetime.now(tz) - session['last_used'] delta = datetime.now(tz) - session['last_used']
if delta.seconds > 600: if delta.seconds > 600:
@ -76,6 +80,27 @@ def auth_required(func):
@auth_required @auth_required
async def index(request): async def index(request):
"""The index page.""" """The index page."""
async with request.app['pool'].acquire() as conn:
avail_sites = await conn.fetch(
"SELECT app_info.name, app_info.url "
"FROM app_info LEFT JOIN app_user "
"ON (app_info.id = app_user.app_id) "
"WHERE app_user.user_id = $1",
request['session']['id'])
if request['session']['admin']:
apps = await conn.fetch(
"SELECT name FROM app_info")
user_perms = await conn.fetch(
"SELECT user_info.id, user_info.username, app_user.app_id "
"FROM user_info LEFT JOIN app_user "
"ON (user_info.id = app_user.user_id)")
if request['session']['admin']:
apps = [app['name'] for app in apps]
users = defaultdict(lambda: [False]*len(apps))
for user_perm in user_perms:
users[user_perm['username']][user_perm['app_id']-1] = True
users_json = json.dumps(users)
return render_template("index.html", request, locals()) return render_template("index.html", request, locals())
@ -101,8 +126,11 @@ async def login(request):
return render_template("login.html", request, locals()) return render_template("login.html", request, locals())
if argon2.verify(password, user_info['password_hash']): if argon2.verify(password, user_info['password_hash']):
index_url = request.app.router['index'].url_for() url = request.cookies.get('redirect')
resp = web.HTTPFound(location=index_url) if not url:
url = request.app.router['index'].url_for()
resp = web.HTTPFound(location=url)
resp.set_cookie('redirect', '', max_age=0)
resp.set_cookie( resp.set_cookie(
'userid', 'userid',
user_info['id'], user_info['id'],
@ -240,7 +268,6 @@ async def get_session(request):
'meta': data_meta, 'meta': data_meta,
'session_data': json.loads(data_meta.pop('session_data'))} 'session_data': json.loads(data_meta.pop('session_data'))}
print(data)
return web.json_response(data) return web.json_response(data)
else: else:
error = {'error': "User ID or Session ID invalid."} error = {'error': "User ID or Session ID invalid."}

46
static/buckler.css Normal file
View File

@ -0,0 +1,46 @@
body {
margin-left: 10%;
margin-right: 10%;
background-color: lightgray;
font-family: Helvetica,sans-serif;
}
header {
margin-bottom: 3em;
display: flex;
}
#logo {
height: 5em;
margin-right: 1em;
}
main {
display: grid;
gap: 2em;
background-color: whitesmoke;
padding: 5%;
border-radius: 0.5em;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 3px 1px -2px rgba(0, 0, 0, 0.2),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
#avail_sites {
margin: 0;
padding-left: 1em;
list-style-type: none;
}
#users {
border: 1px solid lightgray;
border-collapse: collapse;
}
#users tr {
border: 1px solid lightgray;
}
#users td {
text-align: center;
}

20
static/buckler.js Normal file
View File

@ -0,0 +1,20 @@
function perm_change(row) {
let user_perms = users_perms[row.children[0].textContent];
let row_perms = [];
for (let child of row.children) {
if (child.firstChild.type == "checkbox") {
if (child.firstChild.checked) {
row_perms.push(true);
} else {
row_perms.push(false);
}
}
}
let perms_changed = false;
for (let i = 0; i < user_perms.length; i++) {
if (user_perms[i] != row_perms[i]) {
perms_changed = true;
}
}
console.log("perms_changed = " + perms_changed);
}

4
static/buckler_icon.svg Normal file
View File

@ -0,0 +1,4 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="48" stroke="black" fill="none"/>
<circle cx="50" cy="50" r="18" stroke="black" fill="none"/>
</svg>

After

Width:  |  Height:  |  Size: 192 B

View File

@ -2,9 +2,49 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>Buckler</title> <title>Buckler</title>
<script>
var users_perms = {{ users_json|safe }};
</script>
<script type="text/javascript" src="/static/buckler.js"></script>
<link rel="stylesheet" type="text/css" href="/static/buckler.css">
</head> </head>
<body> <body>
<h1>Buckler</h1> <header>
Secret page. <object id="logo" data="/static/buckler_icon.svg"></object>
<h1>Buckler</h1>
</header>
<main>
<div>
Available sites
<ul id="avail_sites">
{% for site in avail_sites %}
<li><a href="{{ site['url'] }}">{{ site['name'] }}</a></li>
{% endfor %}
</ul>
</div>
{% if request['session']['admin'] %}
<table id="users">
<thead>
<tr>
<th>User</th>
{% for app in apps %}
<th>{{ app }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for username, values in users.items() %}
<tr>
<td>{{ username }}</td>
{% for value in values %}
<td><input type="checkbox" onchange="perm_change(this.parentElement.parentElement)"{% if value %} checked{% endif %}></td>
{% endfor %}
<td><input type="submit"></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</main>
</body> </body>
</html> </html>

View File

@ -4,16 +4,20 @@
<title>Buckler - Login</title> <title>Buckler - Login</title>
</head> </head>
<body> <body>
<h1>Buckler Login</h1> <header>
<form action="{{ request.app.router['login'].url_for() }}" method="post" enctype="application/x-www-form-urlencoded"> <h1>Buckler Login</h1>
<label for="username">Username</label> </header>
<input id="username" name="username" type="text"><br> <main>
<label for="password">Password</label> <form action="{{ request.app.router['login'].url_for() }}" method="post" enctype="application/x-www-form-urlencoded">
<input id="password" name="password" type="password"><br> <label for="username">Username</label>
{% if login_failed %} <input id="username" name="username" type="text"><br>
<ul><li>Username and/or password incorrect</li></ul> <label for="password">Password</label>
{% endif %} <input id="password" name="password" type="password"><br>
<input type="submit" value="Login"> {% if login_failed %}
</form> <ul><li>Username and/or password incorrect</li></ul>
{% endif %}
<input type="submit" value="Login">
</form>
</main>
</body> </body>
</html> </html>