commit 9be8a1f54657852b316ae536a75bfd0a8c808aa2
parent 6fb63b1614bea44befce80b6d6ca72c1b0f859f2
Author: parazyd <parazyd@dyne.org>
Date: Sun, 20 Jan 2019 18:45:59 +0100
Add support for user list and profiles.
Diffstat:
7 files changed, 134 insertions(+), 37 deletions(-)
diff --git a/db.py b/db.py
@@ -37,8 +37,7 @@ def initdb(dbpath):
password text NOT NULL,
cap integer NOT NULL,
first_seen integer NOT NULL,
- is_active integer NOT NULL,
- is_authed integer NOT NULL
+ is_active integer NOT NULL
);
'''
@@ -71,7 +70,9 @@ def sql_select_col_where(col0, col1, val, table='stories'):
"""
Queries col0 where col1 = val.
"""
- db.execute("SELECT %s FROM %s WHERE %s = '%s';" % (col0, table, col1, val))
+ db.execute("""
+ SELECT %s FROM %s WHERE %s = '%s';
+ """ % (col0, table, col1, val))
return db.fetchall()
@@ -101,23 +102,12 @@ def sql_update_row_where(vals, col, val, table='stories'):
vals is a list of tuples.
"""
- length = len(vals) - 1
- valstring = ''
- for i, j in enumerate(vals):
- if not isinstance(j[1], int):
- valstring += "%s = '%s'" % (j[0], j[1].replace("'", "''"))
- else:
- valstring += "%s = '%s'" % (j[0], j[1])
- if i < length:
- valstring += ', '
-
- print(valstring)
-
- db.execute("""
- UPDATE %s
- SET %s
- WHERE %s = '%s';
- """ % (table, valstring, col, val))
+ for i in vals:
+ db.execute("""
+ UPDATE %s
+ SET %s = ?
+ WHERE %s = ?;
+ """ % (table, i[0], col), (i[1], val))
dbctx.commit()
@@ -135,13 +125,13 @@ def sql_insert(args):
);
""", (args[0], args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9], args[10]))
- elif len(args) == 8:
+ elif len(args) == 7:
# User
db.execute("""
INSERT INTO users VALUES (
- ?, ?, ?, ?, ?, ?, ?, ?
+ ?, ?, ?, ?, ?, ?, ?
);
""", (args[0], args[1], args[2], args[3], args[4], args[5],
- args[6], args[7]))
+ args[6]))
dbctx.commit()
diff --git a/diaspora.py b/diaspora.py
@@ -22,6 +22,7 @@ from argparse import ArgumentParser
from random import choice
from time import time
+from bcrypt import hashpw, gensalt
from flask import Markup, Flask, render_template, request, url_for, redirect
from flask_login import (LoginManager, UserMixin, login_required, login_user,
logout_user, current_user)
@@ -31,7 +32,7 @@ from db import (sql_delete_row_where, sql_update_row_where, sql_insert,
from utils import (get_story, makenav, randomstring, getcountryname,
get_multiple_stories, get_multiple_stories_filtered,
make_profile, find_user_by_id, find_user_by_email,
- validate_user)
+ validate_user, get_multiple_users)
app = Flask(__name__)
@@ -50,7 +51,7 @@ class LoginUser(UserMixin):
# TODO: Find out if it's possible to do less SQL queries.
def __init__(self, uid):
""" Init """
- self.uid = uid
+ self.id = uid
@property
def username(self):
@@ -74,7 +75,7 @@ class LoginUser(UserMixin):
def get_user(self):
""" Get user struct """
- return find_user_by_id(self.uid)
+ return find_user_by_id(self.id)
@login_manager.user_loader
@@ -265,9 +266,11 @@ def profile():
email = sql_select_col_where('email', 'id', uid, table='users')
if email:
email = email[0][0]
- stories = get_multiple_stories('email', email)
- name = stories[0]['name']
- return render_template('profile.html', stories=stories, name=name)
+ stories = get_multiple_stories_filtered('email', email,
+ ('visible', 1))
+ if stories:
+ name = stories[0]['name']
+ return render_template('profile.html', stories=stories, name=name)
return render_template('fail_profile.html')
@@ -283,7 +286,6 @@ def dashboard():
fparam = {'pending': 0, 'posted': 1}
-
add_id = request.args.get('approveid')
if add_id:
sql_update_row_where([('visible', 1)], 'id', add_id)
@@ -300,6 +302,36 @@ def dashboard():
return render_template('dashboard.html', stories=stories)
+@app.route('/users', methods=['GET', 'POST'])
+#@login_required
+def users():
+ """
+ Route for users view.
+ """
+ #if not current_user.is_admin:
+ # return render_template('fail_permissions.html')
+
+ if request.method == 'POST':
+ vals = []
+ if request.form['password']:
+ vals.append(('password',
+ hashpw(request.form['password'].encode(),
+ gensalt())))
+ if request.form['cap']:
+ vals.append(('cap', request.form['cap']))
+
+ if vals:
+ sql_update_row_where(vals, 'id', request.form['id'], table='users')
+
+ print(vals)
+
+ if request.args.get('delid'):
+ sql_delete_row_where('id', request.args.get('delid'), table='users')
+
+ users = get_multiple_users('is_active', 1)
+ return render_template('users.html', users=users)
+
+
@app.route('/')
def main():
"""
diff --git a/static/css/diaspora.css b/static/css/diaspora.css
@@ -126,5 +126,3 @@ nav {
.countrylist-bottom a {
text-decoration: none;
}
-
-
diff --git a/templates/edit.html b/templates/edit.html
@@ -21,7 +21,7 @@
<main role="main" class="container">
<p>
- <a href="/delete?key={{ story['deletekey'] }}" class="btn btn-danger">Delete this story</a>
+ <a href="/delete?key={{ story['deletekey'] }}" class="btn btn-outline-danger">Delete this story</a>
</p>
<form action="/edit" method="POST" id="storyform">
diff --git a/templates/nav.html b/templates/nav.html
@@ -49,10 +49,16 @@
<a class="dropdown-item" href="/dashboard?list=posted">
<span class="fa fa-envelope-open"></span> Posted stories
</a>
+ <a class="dropdown-item" href="/users">
+ <span class="fa fa-user-circle"></span> Users
+ </a>
</div>
</li>
{% endif %}
<li class="nav-item">
+ <a class="nav-link" href="/profile?id={{ current_user.id }}">Profile</a>
+ </li>
+ <li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
{% else %}
diff --git a/templates/users.html b/templates/users.html
@@ -0,0 +1,57 @@
+{% include 'header.html' %}
+
+ <title>Users | Diaspora Diaries</title>
+
+{% include 'nav.html' %}
+
+ <main role="main" class="container-fluid">
+
+ <h1 class="cover-heading">Users</h1>
+
+ <table class="table">
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Name</th>
+ <th scope="col">Email</th>
+ <th scope="col">Password</th>
+ <th scope="col">Cap</th>
+ <th scope="col">First seen</th>
+ <th scope="col">Apply</th>
+ <th scope="col">Delete</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for i in users %}
+ <tr>
+ <th scope="row">
+ <form action="/users" method="POST" id="form_{{ i['id'] }}">
+ <input type="hidden" name="id" value="{{ i['id'] }}">
+ </form>
+ {{ i['id'] }}
+ </th>
+ <td>
+ <a href="/profile?id={{ i['id'] }}">{{ i['name'] }}</a>
+ </td>
+ <td>{{ i['email'] }}</td>
+ <td><input form="form_{{ i['id'] }}" type="text" name="password" placeholder="New password"></td>
+ <td><input form="form_{{ i['id'] }}" type="text" name="cap" placeholder="{{ i['cap'] }} (0=writer, 2=admin)"></td>
+ <td>{{ i['first_seen'] }}</td>
+ <td>
+ <button type="submit" form="form_{{ i['id'] }}" class="btn btn-outline-success">
+ <span class="fa fa-check"></span>
+ </button>
+ </td>
+ <td>
+ <a href="/users?delid={{ i['id'] }}" class="btn btn-outline-danger">
+ <span class="fa fa-times"></span>
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+
+ </main>
+
+{% include 'footer.html' %}
diff --git a/utils.py b/utils.py
@@ -120,6 +120,22 @@ def get_multiple_stories_filtered(col, val, param, reverse=True):
return filtered_stories
+def get_multiple_users(col, val, reverse=False):
+ """
+ Returns a list of users where col=val.
+ """
+ rows = sql_select_col_where('*', col, val, table='users')
+
+ users = []
+ for i in rows:
+ j = fill_user_dict(i)
+ users.append(j)
+
+ if reverse:
+ return users[::-1]
+ return users
+
+
def makenav(randomize=False):
"""
Queries the disembark column for filling up the by-country dropdown
@@ -146,9 +162,8 @@ def fill_user_dict(row):
'name': row[2],
'password': row[3],
'cap': row[4],
- 'first_seen': row[5],
+ 'first_seen': strftime('%d.%m.%Y. %H:%M UTC', gmtime(row[5])),
'is_active': row[6],
- 'is_authed': row[7],
}
@@ -201,10 +216,9 @@ def make_profile(name, email):
email,
name,
password,
- 0,
+ 2,
int(time()),
1,
- 0,
]
sql_insert(userargs)