rewrite user permissions panel
This commit is contained in:
parent
976ffe4551
commit
fc434f0d62
26
buckler.py
26
buckler.py
|
@ -55,11 +55,13 @@ async def index(request):
|
||||||
request['session']['id'])
|
request['session']['id'])
|
||||||
if request['session']['admin']:
|
if request['session']['admin']:
|
||||||
apps = await conn.fetch(
|
apps = await conn.fetch(
|
||||||
"SELECT id, name FROM app_info")
|
"SELECT id, name FROM app_info ORDER BY id ASC")
|
||||||
|
users = await conn.fetch(
|
||||||
|
"SELECT id, username FROM user_info ORDER BY id ASC")
|
||||||
user_perms = await conn.fetch(
|
user_perms = await conn.fetch(
|
||||||
"SELECT user_info.id, user_info.username, app_user.app_id "
|
"SELECT user_info.id, app_user.app_id "
|
||||||
"FROM user_info LEFT JOIN app_user "
|
"FROM user_info LEFT JOIN app_user "
|
||||||
"ON (user_info.id = app_user.user_id)")
|
"ON (user_info.id = app_user.user_id) ")
|
||||||
fido2_keys = await conn.fetch(
|
fido2_keys = await conn.fetch(
|
||||||
"SELECT * FROM user_credential WHERE user_id = $1",
|
"SELECT * FROM user_credential WHERE user_id = $1",
|
||||||
request['session']['id'])
|
request['session']['id'])
|
||||||
|
@ -70,12 +72,18 @@ async def index(request):
|
||||||
request['session']['id'])
|
request['session']['id'])
|
||||||
|
|
||||||
if request['session']['admin']:
|
if request['session']['admin']:
|
||||||
users = defaultdict(lambda: {app['name']: False for app in apps})
|
user_perms_dict = {}
|
||||||
for user_perm in user_perms:
|
for user in users:
|
||||||
index = tools.find_dict(apps, 'id', user_perm['app_id'])
|
lst = [up for up in user_perms if up['id'] == user['id']]
|
||||||
if index != -1:
|
d = {app['id']: False for app in apps}
|
||||||
users[user_perm['username']][apps[index]['name']] = True
|
for perm in lst:
|
||||||
users_json = json.dumps(users)
|
if perm['app_id'] not in d:
|
||||||
|
continue
|
||||||
|
d[perm['app_id']] = True
|
||||||
|
user_perms_dict[user['id']] = d
|
||||||
|
users_dict = {user['id']: user['username'] for user in users}
|
||||||
|
apps_dict = {app['id']: app['name'] for app in apps}
|
||||||
|
user_perms_json = json.dumps(user_perms_dict)
|
||||||
|
|
||||||
return render_template("index.html", request, locals())
|
return render_template("index.html", request, locals())
|
||||||
|
|
||||||
|
|
33
forms.py
33
forms.py
|
@ -2,6 +2,8 @@
|
||||||
"""
|
"""
|
||||||
Co-routines for handling various forms in Buckler.
|
Co-routines for handling various forms in Buckler.
|
||||||
"""
|
"""
|
||||||
|
import json
|
||||||
|
|
||||||
from passlib.hash import argon2
|
from passlib.hash import argon2
|
||||||
|
|
||||||
import tools
|
import tools
|
||||||
|
@ -26,33 +28,24 @@ async def invite_user(request):
|
||||||
async def change_user_perms(request):
|
async def change_user_perms(request):
|
||||||
"""Allows an admin to change user permissions."""
|
"""Allows an admin to change user permissions."""
|
||||||
data = await request.post()
|
data = await request.post()
|
||||||
|
data = json.loads(data['perms'])
|
||||||
|
|
||||||
pluses = []
|
pluses = []
|
||||||
for key, value in data.items():
|
minuses = []
|
||||||
if key == 'form_name':
|
for user_id, perms in data.items():
|
||||||
continue
|
for app_id, value in perms.items():
|
||||||
username, _, app_name = key.partition('-')
|
if value: # TODO: check for TypeError
|
||||||
pluses.append((username, app_name))
|
pluses.append((int(user_id), int(app_id)))
|
||||||
|
else:
|
||||||
|
minuses.append((int(user_id), int(app_id)))
|
||||||
|
|
||||||
async with request.app['pool'].acquire() as conn:
|
async with request.app['pool'].acquire() as conn:
|
||||||
apps = await conn.fetch(
|
|
||||||
"SELECT id, name FROM app_info")
|
|
||||||
users = {p[0] for p in pluses}
|
|
||||||
minuses = []
|
|
||||||
for user in users:
|
|
||||||
for app in apps:
|
|
||||||
minuses.append((user, app['name']))
|
|
||||||
minuses = [m for m in minuses if m not in pluses]
|
|
||||||
|
|
||||||
await conn.executemany(
|
await conn.executemany(
|
||||||
"INSERT INTO app_user (user_id, app_id) "
|
"INSERT INTO app_user (user_id, app_id) VALUES ($1, $2) "
|
||||||
"VALUES ((SELECT id FROM user_info WHERE username = $1), "
|
|
||||||
"(SELECT id FROM app_info WHERE name = $2)) "
|
|
||||||
"ON CONFLICT ON CONSTRAINT app_user_pkey DO NOTHING",
|
"ON CONFLICT ON CONSTRAINT app_user_pkey DO NOTHING",
|
||||||
pluses)
|
pluses)
|
||||||
await conn.executemany(
|
await conn.executemany(
|
||||||
"DELETE FROM app_user "
|
"DELETE FROM app_user WHERE user_id = $1 AND app_id = $2",
|
||||||
"WHERE user_id = (SELECT id FROM user_info WHERE username = $1) "
|
|
||||||
"AND app_id = (SELECT id FROM app_info WHERE name = $2)",
|
|
||||||
minuses)
|
minuses)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
|
@ -15,44 +15,39 @@ function load() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
document.querySelector('#user_perm_form').addEventListener('submit', submit_user_perms);
|
||||||
}
|
}
|
||||||
|
|
||||||
function perm_change(row) {
|
function submit_user_perms(event) {
|
||||||
let user_perms = users_perms[row.children[0].textContent];
|
event.preventDefault();
|
||||||
let row_perms = {};
|
let perms_diff = {};
|
||||||
for (let child of row.children) {
|
for (let input of event.target.querySelectorAll('input[type=checkbox]')) {
|
||||||
if (child.firstChild.type == "checkbox") {
|
let user_id = input.dataset['userId'];
|
||||||
if (child.firstChild.checked) {
|
let app_id = input.dataset['appId'];
|
||||||
row_perms[child.firstChild.dataset.appName] = true;
|
if (input.checked != user_perms[user_id][app_id]) {
|
||||||
} else {
|
let perms = perms_diff[user_id] || {};
|
||||||
row_perms[child.firstChild.dataset.appName] = false;
|
perms[app_id] = input.checked;
|
||||||
}
|
perms_diff[user_id] = perms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let perms_changed = false;
|
|
||||||
for (let app_name of Object.keys(user_perms)) {
|
|
||||||
if (user_perms[app_name] != row_perms[app_name]) {
|
|
||||||
perms_changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("perms_changed = " + perms_changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
function submit_user_perms(row) {
|
let form_body = {
|
||||||
let row_perms = {};
|
'form_name': 'change_user_perms',
|
||||||
for (let child of row.children) {
|
'perms': JSON.stringify(perms_diff),
|
||||||
if (child.firstChild.type == "checkbox") {
|
|
||||||
if (child.firstChild.checked) {
|
|
||||||
row_perms[child.firstChild.dataset.appName] = true;
|
|
||||||
} else {
|
|
||||||
row_perms[child.firstChild.dataset.appName] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
console.log(row_perms);
|
let payload = [];
|
||||||
|
for (let property in form_body) {
|
||||||
|
let encoded_key = encodeURIComponent(property);
|
||||||
|
let encoded_value = encodeURIComponent(form_body[property]);
|
||||||
|
payload.push(encoded_key + '=' + encoded_value);
|
||||||
|
}
|
||||||
|
payload = payload.join('&');
|
||||||
|
|
||||||
fetch(window.location.pathname, {
|
fetch(window.location.pathname, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
body: row_perms
|
body: payload,
|
||||||
|
}).then(function(response) {
|
||||||
|
window.location.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<title>Buckler</title>
|
<title>Buckler</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/buckler.css">
|
<link rel="stylesheet" type="text/css" href="/static/buckler.css">
|
||||||
<script>
|
<script>
|
||||||
var users_perms = {{ users_json|safe }};
|
var user_perms = {{ user_perms_json|safe }};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="/static/buckler.js"></script>
|
<script type="text/javascript" src="/static/buckler.js"></script>
|
||||||
<script>window.onload = load;</script>
|
<script>window.onload = load;</script>
|
||||||
|
@ -38,23 +38,23 @@
|
||||||
<h3>User Permissions</h3>
|
<h3>User Permissions</h3>
|
||||||
<article style="display: none;">
|
<article style="display: none;">
|
||||||
<hr>
|
<hr>
|
||||||
<form method="post" enctype="application/x-www-form-urlencoded">
|
<form id="user_perm_form">
|
||||||
<input name="form_name" type="hidden" value="change_user_perms">
|
<input name="form_name" type="hidden" value="change_user_perms">
|
||||||
<table id="users">
|
<table id="users">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>User</th>
|
<th>User</th>
|
||||||
{% for app in apps %}
|
{% for app in apps %}
|
||||||
<th>{{ app['name'] }}</th>
|
<th data-app-id="{{ app['id'] }}">{{ app['name'] }}</th>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for username, values in users.items() %}
|
{% for user_id, values in user_perms_dict.items() %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ username }}</td>
|
<td data-user-id="{{ user_id }}">{{ users_dict[user_id] }}</td>
|
||||||
{% for app_name, value in values.items() %}
|
{% for app_id, value in values.items() %}
|
||||||
<td><input aria-label="{{ username }}-{{ app_name }}" name="{{ username }}-{{ app_name }}" data-app-name={{ app_name }} type="checkbox"{% if value %} checked{% endif %}></td>
|
<td><input aria-label="{{ users_dict[user_id] }}-{{ apps_dict[app_id] }}" data-user-id="{{ user_id }}" data-app-id="{{ app_id }}" type="checkbox"{% if value %} checked{% endif %}></td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
11
tools.py
11
tools.py
|
@ -85,14 +85,3 @@ async def validate_register(request, form):
|
||||||
errors['email'].append("Email already in use.")
|
errors['email'].append("Email already in use.")
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
def find_dict(lst, key, value):
|
|
||||||
"""
|
|
||||||
Returns the index of the dictionary in the given `lst` which
|
|
||||||
has d[`key`] == `value`.
|
|
||||||
"""
|
|
||||||
for i, d in enumerate(lst):
|
|
||||||
if d[key] == value:
|
|
||||||
return i
|
|
||||||
return -1
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user