Skip to content

Commit

Permalink
add user management
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
  • Loading branch information
Kwpolska committed Jan 4, 2015
1 parent 578f7ad commit f39210a
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 1 deletion.
3 changes: 3 additions & 0 deletions plugins/webapp/templates/mako/delete_post.tmpl
@@ -1,4 +1,7 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<%block name="content">
<!-- New Page Modal -->
<div class="modal fade" id="newPage" tabindex="-1" role="dialog" aria-labelledby="newPageLabel" aria-hidden="true">
Expand Down
3 changes: 3 additions & 0 deletions plugins/webapp/templates/mako/edit_post.tmpl
@@ -1,4 +1,7 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<%block name="content">
<!-- New Page Modal -->
<div class="modal fade" id="newPage" tabindex="-1" role="dialog" aria-labelledby="newPageLabel" aria-hidden="true">
Expand Down
2 changes: 2 additions & 0 deletions plugins/webapp/templates/mako/webapp_index.tmpl
@@ -1,5 +1,7 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<script src="/static/js/jPages.min.js"></script>
<style type="text/css">
html {
Expand Down
3 changes: 3 additions & 0 deletions plugins/webapp/templates/mako/webapp_profile.tmpl
@@ -1,4 +1,7 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<%block name="content">
<!-- New Page Modal -->
<div class="modal fade" id="newPage" tabindex="-1" role="dialog" aria-labelledby="newPageLabel" aria-hidden="true">
Expand Down
88 changes: 88 additions & 0 deletions plugins/webapp/templates/mako/webapp_users.tmpl
@@ -0,0 +1,88 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<%block name="content">
<!-- New Page Modal -->
<div class="modal fade" id="newPage" tabindex="-1" role="dialog" aria-labelledby="newPageLabel" aria-hidden="true">
<form method="POST" action="/new/page">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="newPageLabel">Create New Page?</h4>
</div>
<div class="modal-body">
<input class="form-control" name="title" id="title" placeholder="Title">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Page</button>
</div>
</div>
</div>
</form>
</div>

<!-- New Post Modal -->
<div class="modal fade" id="newPost" tabindex="-1" role="dialog" aria-labelledby="newPostLabel" aria-hidden="true">
<form method="POST" action="/new/post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="newPostLabel">Create New Post?</h4>
</div>
<div class="modal-body">
<input class="form-control" name="title" id="title" placeholder="Title">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Post</button>
</div>
</div>
</div>
</form>
</div>


<h1 class="title">Users</h1>

<table class="table table-hover">
<thead><tr>
<th>Username</th>
<th>Real name</th>
<th>Can edit users</th>
<th>Actions</th>
</tr></thead>
% for user, data in USERS.items():
<tr>
<td>${user}</td>
<td>${data['name']}</td>
<td>
% if data['can_edit_users']:
<i class="fa fa-check"></i>
% else:
<i class="fa fa-times"></i>
% endif
</td>
<td>
<div class="btn-group" role="group">
<a href="/users/${user}" class="btn btn-info btn-xs"><i class="fa fa-pencil"></i></a>
% if user == USERNAME:
<a href="#" class="btn btn-danger btn-xs disabled"><i class="fa fa-trash"></i></a>
% else:
<a href="/users/${user}/delete" class="btn btn-danger btn-xs"><i class="fa fa-trash"></i></a>
% endif
</div>
</tr>
% endfor
<tr><form action="/users/create/new" method="POST">
<td><input name="name" placeholder="User to create"></td>
<td></td>
<td></td>
<td><button type="submit" class="btn btn-success btn-xs"><i class="fa fa-check"></button></td>
</form></tr>
</table>

</%block>
52 changes: 52 additions & 0 deletions plugins/webapp/templates/mako/webapp_users_delete.tmpl
@@ -0,0 +1,52 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<%block name="content">
<!-- New Page Modal -->
<div class="modal fade" id="newPage" tabindex="-1" role="dialog" aria-labelledby="newPageLabel" aria-hidden="true">
<form method="POST" action="/new/page">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="newPageLabel">Create New Page?</h4>
</div>
<div class="modal-body">
<input class="form-control" name="title" id="title" placeholder="Title">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Page</button>
</div>
</div>
</div>
</form>
</div>

<!-- New Post Modal -->
<div class="modal fade" id="newPost" tabindex="-1" role="dialog" aria-labelledby="newPostLabel" aria-hidden="true">
<form method="POST" action="/new/post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="newPostLabel">Create New Post?</h4>
</div>
<div class="modal-body">
<input class="form-control" name="title" id="title" placeholder="Title">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Post</button>
</div>
</div>
</div>
</form>
</div>


<h1 class="title">Really delete <tt>${user}</tt>?</h1>
<a class="btn btn-danger" href="./really_delete">Yes, really.</a>
<a class="btn btn-default" href="/users">No</a>
</%block>
87 changes: 87 additions & 0 deletions plugins/webapp/templates/mako/webapp_users_edit.tmpl
@@ -0,0 +1,87 @@
<%inherit file="base.tmpl"/>
<%block name="extra_head">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
</%block>
<%block name="content">
<!-- New Page Modal -->
<div class="modal fade" id="newPage" tabindex="-1" role="dialog" aria-labelledby="newPageLabel" aria-hidden="true">
<form method="POST" action="/new/page">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="newPageLabel">Create New Page?</h4>
</div>
<div class="modal-body">
<input class="form-control" name="title" id="title" placeholder="Title">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Page</button>
</div>
</div>
</div>
</form>
</div>

<!-- New Post Modal -->
<div class="modal fade" id="newPost" tabindex="-1" role="dialog" aria-labelledby="newPostLabel" aria-hidden="true">
<form method="POST" action="/new/post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="newPostLabel">Create New Post?</h4>
</div>
<div class="modal-body">
<input class="form-control" name="title" id="title" placeholder="Title">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create Post</button>
</div>
</div>
</div>
</form>
</div>

% if not new:
<h1 class="title">Editing profile <tt>${name}</tt></h1>
% else:
<h1 class="title">Creating profile <tt>${name}</tt></h1>
% endif

<form action="/users/${name}/save" method="POST">
<div class="form-group">
<label for="name">Real name</label>
<input class="form-control" id="name" name="name" value="${user['name']}"
placeholder="Real name" required>
</div>
<div class="form-group">
% if user['password']:
<label for="passwd">New password (leave empty to keep previous):</label>
% else:
<label for="passwd">Password:</label>
% endif
<input type="password" class="form-control" id="password" name="password"
% if user['password']:
placeholder="New password"
% else:
placeholder="Password" required
% endif
>
</div>
<div class="checkbox"><label>
<input type="checkbox" name="can_edit_users"
% if user['can_edit_users']:
checked
% endif
% if name == USERNAME:
disabled
% endif
> Can edit users
</label></div>
<button type="submit" class="btn btn-default">Save</button>
</form>

</%block>
101 changes: 100 additions & 1 deletion plugins/webapp/webapp.py
Expand Up @@ -70,7 +70,18 @@ def write_users():
json.dump(USERS, fh, indent=4)

def generate_menu_alt():
return """<li><a href="/profile">{0} [{1}]</a></li>""".format(REALNAME, USERNAME)
if USERS[USERNAME]['can_edit_users']:
edit_entry = '<li><a href="/users">Manage users</a></li>'
else:
edit_entry = ''
return """
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{0} [{1}] <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/profile">Profile</a></li>
{2}
</ul>
</li>""".format(REALNAME, USERNAME, edit_entry)

read_users()

Expand Down Expand Up @@ -263,6 +274,94 @@ def acp_profile_save():
write_users()
b.redirect('/profile')

@staticmethod
@b.route('/users')
@b.auth_basic(auth_check, auth_title)
def acp_users():
global USERS
if not USERS[USERNAME]['can_edit_users']:
b.abort(401, "Not authorized to edit users.")
else:
return render('webapp_users.tmpl',
context={'title': 'Edit users',
'permalink': '/users',
'USERS': USERS})
@staticmethod
@b.route('/users/<name>')
@b.auth_basic(auth_check, auth_title)
def acp_users_edit(name):
global USERS
if not USERS[USERNAME]['can_edit_users']:
b.abort(401, "Not authorized to edit users.")
else:
if name in USERS:
new = False
user = USERS[name]
else:
new = True
user = {'name': '', 'password': '', 'can_edit_users': False}
return render('webapp_users_edit.tmpl',
context={'title': 'Edit user ' + name,
'permalink': '/users/' + name,
'user': user,
'name': name,
'new': new})

@staticmethod
@b.route('/users/<name>/save', method='POST')
@b.auth_basic(auth_check, auth_title)
def acp_users_save(name):
global USERS
if not USERS[USERNAME]['can_edit_users']:
b.abort(401, "Not authorized to edit users.")
else:
read_users()
data = b.request.forms.decode('utf-8')
if name not in USERS:
USERS[name] = {'name': '', 'password': '', 'can_edit_users': False}
if data['password'].strip():
USERS[name]['password'] = passwd_hash(data['password'])
USERS[name]['name'] = data['name']
if name != USERNAME:
USERS[name]['can_edit_users'] = 'can_edit_users' in data
write_users()
b.redirect('/users')

@staticmethod
@b.route('/users/create/new', method='POST')
@b.auth_basic(auth_check, auth_title)
def acp_users_create_new():
data = b.request.forms.decode('utf-8')
b.redirect('/users/' + data['name'])

@staticmethod
@b.route('/users/<name>/delete')
@b.auth_basic(auth_check, auth_title)
def acp_users_delete(name):
global USERS
if not USERS[USERNAME]['can_edit_users']:
b.abort(401, "Not authorized to edit users.")
else:
if name not in USERS:
b.abort(404, "User does not exist.")
return render('webapp_users_delete.tmpl',
context={'title': 'Deleting ' + name,
'permalink': '/users/{0}/delete'.format(name),
'user': name})

@staticmethod
@b.route('/users/<name>/really_delete')
@b.auth_basic(auth_check, auth_title)
def acp_users_really_delete(name):
global USERS
if not USERS[USERNAME]['can_edit_users']:
b.abort(401, "Not authorized to edit users.")
else:
read_users()
del USERS[name]
write_users()
b.redirect('/users')

def render(template_name, context=None):
if context is None:
context = {}
Expand Down

0 comments on commit f39210a

Please sign in to comment.