Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
commit 604b0ff75466a076bf9b8b5dcc20bde5fa1cd088 Author: Bohuslav Kabrda bkabrda@redhat.com Date: Thu Mar 28 15:46:04 2013 +0100
Start implementing admin section in frontend
coprs_frontend/coprs/__init__.py | 3 ++ coprs_frontend/coprs/helpers.py | 4 ++ coprs_frontend/coprs/templates/admin/index.html | 5 +++ coprs_frontend/coprs/templates/admin/layout.html | 8 +++++ coprs_frontend/coprs/views/admin_ns/__init__.py | 3 ++ .../coprs/views/admin_ns/admin_general.py | 11 +++++++ coprs_frontend/coprs/views/misc.py | 30 ++++++++++++++------ coprs_frontend/tests/coprs_test_case.py | 6 ++-- .../test_views/test_admin/test_admin_general.py | 20 +++++++++++++ 9 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/coprs_frontend/coprs/__init__.py b/coprs_frontend/coprs/__init__.py index 6a9290c..103d7e1 100644 --- a/coprs_frontend/coprs/__init__.py +++ b/coprs_frontend/coprs/__init__.py @@ -25,6 +25,8 @@ import coprs.log import coprs.models import coprs.whoosheers
+from coprs.views import admin_ns +from coprs.views.admin_ns import admin_general from coprs.views import api_ns from coprs.views.api_ns import api_general from coprs.views import coprs_ns @@ -35,6 +37,7 @@ from coprs.views.backend_ns import backend_general from coprs.views import misc
app.register_blueprint(api_ns.api_ns) +app.register_blueprint(admin_ns.admin_ns) app.register_blueprint(coprs_ns.coprs_ns) app.register_blueprint(misc.misc) app.register_blueprint(backend_ns.backend_ns) diff --git a/coprs_frontend/coprs/helpers.py b/coprs_frontend/coprs/helpers.py index 15e942e..fdc87af 100644 --- a/coprs_frontend/coprs/helpers.py +++ b/coprs_frontend/coprs/helpers.py @@ -43,6 +43,10 @@ class BackendResultEnum(object): __metaclass__ = EnumType vals = {'waiting': 0, 'success': 1, 'failure': 2}
+class RoleEnum(object): + __metaclass__ = EnumType + vals = {'user': 0, 'admin': 1} + class Paginator(object): def __init__(self, query, total_count, page = 1, per_page_override = None, urls_count_override = None): self.query = query diff --git a/coprs_frontend/coprs/templates/admin/index.html b/coprs_frontend/coprs/templates/admin/index.html new file mode 100644 index 0000000..25562a2 --- /dev/null +++ b/coprs_frontend/coprs/templates/admin/index.html @@ -0,0 +1,5 @@ +{% extends "admin/layout.html" %} + +{% block admin_body %} +Admin body +{% endblock %} diff --git a/coprs_frontend/coprs/templates/admin/layout.html b/coprs_frontend/coprs/templates/admin/layout.html new file mode 100644 index 0000000..336e077 --- /dev/null +++ b/coprs_frontend/coprs/templates/admin/layout.html @@ -0,0 +1,8 @@ +{% extends "layout.html" %} + +{% block title %}Coprs - Admin{% endblock %} + +{% block body %} +Admin menu +{% block admin_body %}{% endblock %} +{% endblock %} diff --git a/coprs_frontend/coprs/views/admin_ns/__init__.py b/coprs_frontend/coprs/views/admin_ns/__init__.py new file mode 100644 index 0000000..b7f5426 --- /dev/null +++ b/coprs_frontend/coprs/views/admin_ns/__init__.py @@ -0,0 +1,3 @@ +import flask + +admin_ns = flask.Blueprint('admin_ns', __name__, url_prefix = '/admin') diff --git a/coprs_frontend/coprs/views/admin_ns/admin_general.py b/coprs_frontend/coprs/views/admin_ns/admin_general.py new file mode 100644 index 0000000..8252c5e --- /dev/null +++ b/coprs_frontend/coprs/views/admin_ns/admin_general.py @@ -0,0 +1,11 @@ +import flask + +from coprs import helpers + +from coprs.views.admin_ns import admin_ns +from coprs.views.misc import login_required + +@admin_ns.route('/') +@login_required(role=helpers.RoleEnum('admin')) +def admin_index(): + return flask.render_template('admin/index.html') diff --git a/coprs_frontend/coprs/views/misc.py b/coprs_frontend/coprs/views/misc.py index 1c5a47c..7ffad6b 100644 --- a/coprs_frontend/coprs/views/misc.py +++ b/coprs_frontend/coprs/views/misc.py @@ -107,15 +107,27 @@ def api_login_required(f): return decorated_function
-def login_required(f): - @functools.wraps(f) - def decorated_function(*args, **kwargs): - if flask.g.user is None: - return flask.redirect(flask.url_for('misc.login', - next = flask.request.url)) - return f(*args, **kwargs) - return decorated_function - +def login_required(role=helpers.RoleEnum('user')): + def view_wrapper(f): + @functools.wraps(f) + def decorated_function(*args, **kwargs): + if flask.g.user is None: + return flask.redirect(flask.url_for('misc.login', + next = flask.request.url)) + if role == helpers.RoleEnum('admin') and not flask.g.user.admin: + flask.flash('You are not allowed to access admin section.') + return flask.redirect(flask.url_for('coprs_ns.coprs_show')) + return f(*args, **kwargs) + return decorated_function + # hack: if login_required is used without params, the "role" parameter + # is in fact the decorated function, so we need to return + # the wrapped function, not the wrapper + # proper solution would be to use login_required() with parentheses + # everywhere, even if they're empty - TODO + if callable(role): + return view_wrapper(role) + else: + return view_wrapper
# backend authentication def backend_authenticated(f): diff --git a/coprs_frontend/tests/coprs_test_case.py b/coprs_frontend/tests/coprs_test_case.py index 4f6043f..bea1f58 100644 --- a/coprs_frontend/tests/coprs_test_case.py +++ b/coprs_frontend/tests/coprs_test_case.py @@ -40,9 +40,9 @@ class CoprsTestCase(object):
@pytest.fixture def f_users(self): - self.u1 = models.User(openid_name = u'http://user1.id.fedoraproject.org/', proven = False, mail = 'user1@foo.bar') - self.u2 = models.User(openid_name = u'http://user2.id.fedoraproject.org/', proven = False, mail = 'user2@spam.foo') - self.u3 = models.User(openid_name = u'http://user3.id.fedoraproject.org/', proven = False, mail = 'baz@bar.bar') + self.u1 = models.User(openid_name=u'http://user1.id.fedoraproject.org/', proven=False, admin=True, mail='user1@foo.bar') + self.u2 = models.User(openid_name=u'http://user2.id.fedoraproject.org/', proven = False, mail='user2@spam.foo') + self.u3 = models.User(openid_name=u'http://user3.id.fedoraproject.org/', proven=False, mail='baz@bar.bar')
self.db.session.add_all([self.u1, self.u2, self.u3])
diff --git a/coprs_frontend/tests/test_views/test_admin/test_admin_general.py b/coprs_frontend/tests/test_views/test_admin/test_admin_general.py new file mode 100644 index 0000000..1223934 --- /dev/null +++ b/coprs_frontend/tests/test_views/test_admin/test_admin_general.py @@ -0,0 +1,20 @@ +from tests.coprs_test_case import CoprsTestCase + +class TestAdminLogin(CoprsTestCase): + # TODO: test on something better then page title - maybe see rendered templates? + text_to_check = 'Coprs - Admin' + def test_nonadmin_cant_login(self, f_users, f_db): + with self.tc as c: + with c.session_transaction() as s: + s['openid'] = self.u2.openid_name + + r = c.get('/admin/', follow_redirects=True) + assert self.text_to_check not in r.data + + def test_admin_can_login(self, f_users, f_db): + with self.tc as c: + with c.session_transaction() as s: + s['openid'] = self.u1.openid_name + + r = c.get('/admin/', follow_redirects=True) + assert self.text_to_check in r.data
copr-devel@lists.fedorahosted.org