-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
134 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
bp = Blueprint('admin', __name__) | ||
|
||
|
||
@bp.record_once | ||
def register(state): | ||
from sopy.admin import views |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,34 @@ | ||
from wtforms import ValidationError | ||
from flask.ext.wtf import Form | ||
from flask_wtf import Form | ||
from wtforms.fields import StringField | ||
from wtforms.validators import Required | ||
|
||
from wtforms.validators import ValidationError, InputRequired | ||
from sopy import db | ||
from sopy.auth.models import User | ||
|
||
|
||
class EditUserGroupsForm(Form): | ||
""" a form to add a user to a group """ | ||
user_id = StringField('user id', validators=[Required()]) | ||
class UserListForm(Form): | ||
user_ids = StringField('User IDs', validators=[InputRequired()]) | ||
|
||
def validate_user_ids(self, field): | ||
raw_ids = field.data.split() | ||
int_ids = set() | ||
|
||
for id in raw_ids: | ||
try: | ||
int_ids.add(int(id)) | ||
except TypeError: | ||
raise ValidationError('Invalid ID "{}"'.format(id)) | ||
|
||
q_ids = db.session.query(db.cast(db.func.unnest(field.data.split()), db.Integer).label('id')).subquery() | ||
users = User.query.join((q_ids, q_ids.c.id == User.id)).all() | ||
new_ids = int_ids - {u.id for u in users} | ||
|
||
for id in new_ids: | ||
#TODO: use api to load multiple users in one request | ||
user = User.se_load(id) | ||
|
||
if user is None: | ||
raise ValidationError('Invalid ID "{}"'.format(id)) | ||
|
||
users.append(user) | ||
|
||
def validate_user_id(self, field): | ||
""" check that the user ID exists in the db """ | ||
if User.query.get(field.data) is None: | ||
raise ValidationError('No user with that ID exists') | ||
self.users = users |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,42 @@ | ||
from flask import abort, render_template, request | ||
|
||
from sopy import db | ||
from sopy.admin import bp | ||
from sopy.admin.forms import EditUserGroupsForm | ||
from sopy.admin.forms import UserListForm | ||
from sopy.ext.views import template, redirect_for | ||
from sopy.auth.models import User, Group | ||
from sopy.auth.login import has_group, current_user, login_required | ||
from sopy.auth.login import group_required | ||
|
||
|
||
@bp.before_request | ||
@login_required | ||
@group_required('approved') | ||
def authorize(): | ||
""" Check that the user has privileges to access this page. """ | ||
if not current_user.has_group('approved'): | ||
abort(403) # page forbidden | ||
|
||
|
||
@bp.route('/groups') | ||
@template('admin/view_all_groups.html') | ||
def view_all_groups(): | ||
""" returns all distinct groups in the database, adds links to the page | ||
note: the links are not very pretty. """ | ||
groups = Group.query.distinct() | ||
return {'groups': groups} | ||
|
||
|
||
@bp.route('/groups/<group_name>', methods=['GET', 'POST']) | ||
@template('/admin/view_group.html') | ||
def view_group(group_name): | ||
""" Find all groups, and the users which belong to them. """ | ||
selected_group = User.query.filter(User._groups.any(Group.name == group_name)).all() | ||
form = EditUserGroupsForm() | ||
pass | ||
|
||
|
||
@bp.route('/groups/') | ||
@template('admin/groups/index.html') | ||
def groups_index(): | ||
return {'groups': Group.query.order_by(Group.name).all()} | ||
|
||
|
||
@bp.route('/groups/<name>/', methods=['GET', 'POST']) | ||
@template('/admin/groups/detail.html') | ||
def groups_detail(name): | ||
group = Group.query.options(db.joinedload(Group.users)).filter(Group.name == name).first_or_404() | ||
form = UserListForm() | ||
|
||
if form.validate_on_submit(): | ||
user = User.query.get(form.user_id.data) | ||
group = Group.query.filter_by(name=group_name).one() | ||
user._groups.add(group) | ||
group.users.update(form.users) | ||
db.session.commit() | ||
return redirect_for('admin.view_group', group_name=group_name) | ||
return {'group': group_name, 'group_users': selected_group, 'form': form} | ||
|
||
return redirect_for('admin.groups_detail', name=name) | ||
|
||
return {'group': group, 'form': form} | ||
|
||
@bp.route('/groups/<group_name>/remove/<int:user_id>') | ||
def remove_user_from_group(group_name, user_id): | ||
""" remove a specified user from a group """ | ||
user = User.query.get_or_404(user_id) | ||
group = Group.query.filter_by(name=group_name).one() | ||
user._groups.discard(group) | ||
|
||
@bp.route('/groups/<name>/remove/<int:user_id>') | ||
def groups_remove_user(name, user_id): | ||
user = User.query.options(db.joinedload(User._groups)).get_or_404(user_id) | ||
user.groups.discard(name) | ||
db.session.commit() | ||
return redirect_for('admin.view_group', group_name=group_name) | ||
|
||
return redirect_for('admin.groups_detail', name=name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{% extends "base.html" %} | ||
{% extends 'base.html' %} | ||
|
||
{% block nav_admin %}active{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{% extends "admin/base.html" %} | ||
|
||
{% block content %} | ||
<div class="row"><div class="col-md-12"> | ||
<h2 class="page-header">{% block title %}{{ group.name }}{% endblock %}</h2> | ||
|
||
<form method="post" class="form-inline"> | ||
{{ form.hidden_tag() }} | ||
<div class="form-group{% if form.user_ids.errors %} has-error{% endif %}"> | ||
{{ form.user_ids.label(class='sr-only') }} | ||
{{ form.user_ids(class='form-control', placeholder=form.user_ids.label.text) }} | ||
</div> | ||
<button type="submit" class="btn btn-success"><i class="fa fa-plus"></i> Add Users</button> | ||
</form> | ||
|
||
<hr/> | ||
|
||
<table class="table table-bordered table-striped table-hover"> | ||
<thead> | ||
<tr> | ||
<th class="col-sm-1">ID</th> | ||
<th>Name</th> | ||
<th class="col-sm-1"></th> | ||
</tr> | ||
</thead> | ||
|
||
<tbody> | ||
{% for user in group.users|sort(attribute='id') %} | ||
<tr> | ||
<td>{{ user.id }}</td> | ||
<td><img src="{{ user.profile_image }}" alt="" height="24"/> {{ user.display_name }}</td> | ||
<td><a href="{{ url_for('admin.groups_remove_user', name=group.name, user_id=user.id) }}" class="btn btn-danger btn-block btn-xs"><i class="fa fa-minus"></i> Remove</a></td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
</div></div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{% extends 'admin/base.html' %} | ||
|
||
{% block content %} | ||
<div class="row"><div class="col-md-12"> | ||
<h2 class="page-header">{% block title %}Groups{% endblock %}</h2> | ||
|
||
<ul>{% for group in groups %} | ||
<li><a href="{{ url_for('admin.groups_detail', name=group.name) }}">{{ group.name }}</a></li> | ||
{% endfor %}</ul> | ||
</div></div> | ||
{% endblock %} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters