Skip to content

Commit

Permalink
Merge branch 'release/0.6.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
mblomdahl committed Dec 11, 2017
2 parents f5b142a + 16478c3 commit dc03359
Show file tree
Hide file tree
Showing 39 changed files with 1,791 additions and 368 deletions.
9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ DB Models
Changelog
=========

v. 0.6.3
--------

* Added "view collection" link to user profile page
* *Terms of Service* view added, requesting the user to approve
* Bug fix for loading Voyager permissions on SEK
(`#113 <https://github.com/libris/xl_auth/issues/113>`_)


v. 0.6.2
--------

Expand Down
10 changes: 8 additions & 2 deletions assets/css/style.less
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ td,th {
&.word-break-all {
word-break: break-all;
}
&.min-width-120px {
min-width: 120px;
}
&.min-width-110px {
min-width: 110px;
}
&.min-width-100px {
min-width: 100px;
}
Expand Down Expand Up @@ -127,11 +133,11 @@ td,th {
/* Definition Lists */

.dl-horizontal dt {
width: 240px;
width: 210px;
}

.dl-horizontal dd {
margin-left: 260px;
margin-left: 230px;
}

/* Footer */
Expand Down
436 changes: 293 additions & 143 deletions messages.pot

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions migrations/versions/7f3f1a931278_add_tos_approved_at_to_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Add 'tos_approved_at' to User.
Revision ID: 7f3f1a931278
Revises: b984311d26d7
Create Date: 2017-11-29 14:42:23.349903
"""

from __future__ import absolute_import, division, print_function, unicode_literals

import sqlalchemy as sa
from alembic import op

# Revision identifiers, used by Alembic.
revision = '7f3f1a931278'
down_revision = 'b984311d26d7'
branch_labels = None
depends_on = None


def upgrade():
"""Add 'users.tos_approved_at' column."""
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.add_column(sa.Column('tos_approved_at', sa.DateTime(), nullable=True))


def downgrade():
"""Drop 'users.tos_approved_at' column."""
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.drop_column('tos_approved_at')
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "xl_auth",
"version": "0.6.2",
"version": "0.6.3",
"author": "National Library of Sweden",
"license": "Apache-2.0",
"description": "OAuth2 authorization for LibrisXL, replacing BibDB counterpart",
"description": "Authorization and OAuth2 provider for LibrisXL",
"homepage": "https://github.com/libris/xl_auth#readme",
"bugs": {
"url": "https://github.com/libris/xl_auth/issues"
Expand Down
4 changes: 2 additions & 2 deletions tests/end2end/test_collection_editing.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_superuser_can_edit_existing_collection(superuser, collection, testapp):
# Submits
res = form.submit().follow()
# Clicks Collections button
res = res.click(href=url_for('collection.home'))
res = res.click(href=url_for('collection.home'), index=0)
# Clicks Edit button
res = res.click(href='/collections/edit/' + collection.code)
# Fills out the form
Expand Down Expand Up @@ -158,7 +158,7 @@ def test_user_cannot_edit_collection(user, collection, testapp):
res = form.submit().follow()

# We click the Collections button
res = res.click(href=url_for('collection.home'))
res = res.click(href=url_for('collection.home'), index=0)

# No Edit buttons for regular users
assert res.lxml.xpath("//a[contains(@text,'{0}')]".format(_('Edit'))) == []
Expand Down
4 changes: 2 additions & 2 deletions tests/end2end/test_collection_registering.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_superuser_can_register_new_collection(superuser, testapp):
# Submits
res = form.submit().follow()
# Clicks Collections button
res = res.click(href=url_for('collection.home'))
res = res.click(href=url_for('collection.home'), index=0)
# Clicks Register New Collection button
res = res.click(_('New Collection'))
# Fills out the form
Expand Down Expand Up @@ -168,7 +168,7 @@ def test_user_cannot_register_collection(user, collection, testapp):
res = form.submit().follow()

# We click the Collections button
res = res.click(href=url_for('collection.home'))
res = res.click(href=url_for('collection.home'), index=0)

# No New Collection button for regular users
assert res.lxml.xpath("//a[contains(@text,'{0}')]".format(_('New Collection'))) == []
Expand Down
186 changes: 186 additions & 0 deletions tests/end2end/test_collection_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# -*- coding: utf-8 -*-
"""Test viewing collection."""

from __future__ import absolute_import, division, print_function, unicode_literals

from flask import escape, url_for
from flask_babel import gettext as _

from ..factories import CollectionFactory, PermissionFactory


def test_user_can_view_collection_info(permission, testapp):
"""View info about one of the user's collections."""
# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = permission.user.email
form['password'] = 'example'
# Submits.
res = form.submit().follow()
# Clicks 'view collection' on profile page
res = res.click(href=url_for('collection.view', collection_code=permission.collection.code))
# Sees collection info.
assert res.status_code is 200
assert _('View Collection \'%(code)s\'', code=permission.collection.code) in res


def test_user_sees_error_message_if_collection_code_does_not_exist(user, testapp):
"""Show error when attempting to view a permission that does not exist."""
# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = user.email
form['password'] = 'myPrecious'
# Submits.
res = form.submit().follow()
assert res.status_code is 200
# Fails to figures out the correct ID for another user.
res = testapp.get(url_for('collection.view', collection_code='FAKE1')).follow()
# Sees error message.
assert escape(_('Collection code "%(code)s" does not exist', code='FAKE1')) in res


def test_superuser_can_view_all_permissions_on_collection(superuser, permission, testapp):
"""View all permissions as superuser."""
# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = superuser.email
form['password'] = 'myPrecious'
# Submits.
res = form.submit().follow()
assert res.status_code is 200
# Goes to the right URL for viewing a collection.
res = testapp.get(url_for('collection.view', collection_code=permission.collection.code))
assert res.status_code is 200
# Sees all permissions.
assert _('Permissions') in res
assert permission.user.email in res


def test_cataloging_admin_can_view_all_permissions_on_own_collection(user, collection, testapp):
"""View all permissions on a collection that you're managing."""
# Add cataloging admin permission.
cataloging_admin_permission = PermissionFactory(user=user, collection=collection,
cataloging_admin=True)
cataloging_admin_permission.save()
# Add 2nd cataloger+registrant permission.
other_users_non_cataloging_admin_permission = PermissionFactory(collection=collection,
cataloging_admin=False)
other_users_non_cataloging_admin_permission.save()
# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = user.email
form['password'] = 'myPrecious'
# Submits.
res = form.submit().follow()
assert res.status_code is 200
# Goes to the right URL for viewing a collection.
res = testapp.get(url_for('collection.view',
collection_code=cataloging_admin_permission.collection.code))
assert res.status_code is 200
# Sees all permissions.
assert _('Permissions') in res
assert cataloging_admin_permission.user.email in res
assert other_users_non_cataloging_admin_permission.user.email in res


def test_cataloging_admin_sees_only_cataloging_admins_on_others_collection(user, collection,
testapp):
"""View only 'cataloging_admin' permissions on a collection that you're NOT managing."""
# Add cataloging admin permission.
cataloging_admin_permission = PermissionFactory(user=user, collection=collection,
cataloging_admin=True)
cataloging_admin_permission.save()
other_collection = CollectionFactory().save()
# Add cataloger/registrant permission on 'other_collection'.
other_users_non_cataloging_admin_permission = PermissionFactory(collection=other_collection,
cataloging_admin=False)
other_users_non_cataloging_admin_permission.save()
# Add cataloging admin on 'other_collection'.
other_user_with_cataloging_admin_permission = PermissionFactory(collection=other_collection,
cataloging_admin=True)
other_user_with_cataloging_admin_permission.save()
# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = user.email
form['password'] = 'myPrecious'
# Submits.
res = form.submit().follow()
assert res.status_code is 200
# Goes to the right URL for viewing a collection.
res = testapp.get(url_for('collection.view', collection_code=other_collection.code))
assert res.status_code is 200
# Sees a subset of permissions.
assert _('Cataloging Admins') in res
assert _('Permissions') in res
assert _('You will only see all permissions for those collections that you are '
'cataloging admin for.') in res
assert other_users_non_cataloging_admin_permission.user.email not in res
assert other_user_with_cataloging_admin_permission.user.email in res


def test_non_cataloging_admin_user_sees_permissions_table_on_collections_they_have_permissions_for(
user, collection, testapp):
"""View own and 'cataloging_admin' permissions on collection thyself is associated with."""
# Preconditions.
cataloging_admin_permission = PermissionFactory(collection=collection, cataloging_admin=True)
others_regular_permission = PermissionFactory(collection=collection, cataloging_admin=False)
own_regular_permission = PermissionFactory(user=user, collection=collection,
cataloging_admin=False)
# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = user.email
form['password'] = 'myPrecious'
# Submits.
res = form.submit().follow()
assert res.status_code is 200
# Goes to the right URL for viewing a collection.
res = testapp.get(url_for('collection.view', collection_code=collection.code))
assert res.status_code is 200
# Sees a subset of permissions.
assert _('Cataloging Admins') in res
assert _('Permissions') in res
assert _('You will only see all permissions for those collections that you are '
'cataloging admin for.') in res
assert cataloging_admin_permission.user.email in res
assert others_regular_permission.user.email not in res
assert own_regular_permission.user.email in res


def test_non_cataloging_admin_users_sees_only_cataloging_admins_on_unassociated_collections(
user, collection, testapp):
"""Sees cataloging admins' list only when viewing a collection they are not associated with."""
# Preconditions.
cataloging_admin_permission = PermissionFactory(collection=collection, cataloging_admin=True)
assert user.has_any_permission_for(collection) is False

# Goes to homepage.
res = testapp.get('/')
# Fills out login form.
form = res.forms['loginForm']
form['username'] = user.email
form['password'] = 'myPrecious'
# Submits.
res = form.submit().follow()
assert res.status_code is 200
# Goes to the right URL for viewing a collection.
res = testapp.get(url_for('collection.view', collection_code=collection.code))
assert res.status_code is 200
# Sees cataloging admins' list.
assert _('Cataloging Admins') in res
assert cataloging_admin_permission.user.email in res
# Does not see permissions table.
assert _('Permissions') not in res
assert _('You will only see all permissions for those collections that you are '
'cataloging admin for.') not in res
25 changes: 24 additions & 1 deletion tests/end2end/test_oauth_client_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from xl_auth.oauth.grant.models import Grant
from xl_auth.oauth.token.models import Token

from ..factories import PermissionFactory
from ..factories import CollectionFactory, PermissionFactory


def test_oauth_authorize_success(user, client, testapp):
Expand Down Expand Up @@ -171,6 +171,29 @@ def test_verify_success_response(token, testapp):
assert permission['friendly_name'] == permission2.collection.friendly_name


def test_verify_returns_permissions_on_active_collections_only(token, testapp):
"""Get user details and token expiry."""
inactive_collection = CollectionFactory(is_active=False)
permission1 = PermissionFactory(user=token.user, collection=inactive_collection,
registrant=True, cataloger=False)
permission1.save()

active_collection = CollectionFactory(is_active=True)
permission2 = PermissionFactory(user=token.user, collection=active_collection,
registrant=False, cataloger=True)
permission2.save()

res = testapp.get(url_for('oauth.verify'),
headers={'Authorization': str('Bearer ' + token.access_token)})

assert len(res.json_body['user']['permissions']) == 1
returned_permission = res.json_body['user']['permissions'][0]
assert returned_permission['code'] == active_collection.code
assert returned_permission['registrant'] == permission2.registrant
assert returned_permission['cataloger'] == permission2.cataloger
assert returned_permission['friendly_name'] == active_collection.friendly_name


def test_verify_without_bearer(testapp):
"""Attempt getting expiry and user details without 'Bearer' header."""
res = testapp.get(url_for('oauth.verify'), expect_errors=True)
Expand Down
Loading

0 comments on commit dc03359

Please sign in to comment.