Skip to content

Commit

Permalink
global: admin views for invenio-oauth
Browse files Browse the repository at this point in the history
Signed-off-by: Bruno Cuc <bruno.cuc@cern.ch>
  • Loading branch information
Bruno Cuc committed Jan 15, 2016
1 parent de1682a commit 82b09a7
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 17 deletions.
17 changes: 16 additions & 1 deletion examples/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@
from flask_babelex import Babel
from flask_cli import FlaskCLI
from flask_oauthlib.client import OAuth as FlaskOAuth
from invenio_accounts import InvenioAccounts
from invenio_admin import InvenioAdmin
from invenio_db import InvenioDB

from invenio_accounts import InvenioAccounts
from invenio_oauthclient import InvenioOAuthClient

# Create Flask application
Expand All @@ -62,9 +63,23 @@
'SQLALCHEMY_DATABASE_URI', 'sqlite:///app.db'
)

app.config.update(
ACCOUNTS_USE_CELERY=False,
CELERY_ALWAYS_EAGER=True,
CELERY_CACHE_BACKEND="memory",
CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
CELERY_RESULT_BACKEND="cache",
MAIL_SUPPRESS_SEND=True,
SECRET_KEY="CHANGE_ME",
SECURITY_PASSWORD_SALT="CHANGE_ME_ALSO",
)

FlaskCLI(app)
Babel(app)
InvenioDB(app)
InvenioAccounts(app)
FlaskOAuth(app)
InvenioOAuthClient(app)

InvenioAdmin(app, permission_factory=lambda x: x,
view_class_factory=lambda x: x)
1 change: 1 addition & 0 deletions examples/cern_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
from invenio_accounts import InvenioAccounts
from invenio_accounts.views import blueprint as blueprint_user
from invenio_db import InvenioDB

from invenio_oauthclient import InvenioOAuthClient
from invenio_oauthclient.contrib import cern
from invenio_oauthclient.views.client import blueprint as blueprint_client
Expand Down
2 changes: 1 addition & 1 deletion examples/github_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@
from flask import Flask, redirect, url_for
from flask_babelex import Babel
from flask_cli import FlaskCLI
from flask_security import current_user
from flask_menu import Menu as FlaskMenu
from flask_oauthlib.client import OAuth as FlaskOAuth
from flask_security import current_user
from invenio_accounts import InvenioAccounts
from invenio_accounts.views import blueprint as blueprint_user
from invenio_db import InvenioDB
Expand Down
4 changes: 2 additions & 2 deletions examples/orcid_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,18 @@
from flask import Flask, redirect, url_for
from flask_babelex import Babel
from flask_cli import FlaskCLI
from flask_security import current_user
from flask_menu import Menu as FlaskMenu
from flask_oauthlib.client import OAuth as FlaskOAuth
from flask_security import current_user
from invenio_accounts import InvenioAccounts
from invenio_accounts.views import blueprint as blueprint_user
from invenio_db import InvenioDB
from invenio_mail import InvenioMail as Mail

from invenio_oauthclient import InvenioOAuthClient
from invenio_oauthclient.contrib import orcid
from invenio_oauthclient.views.client import blueprint as blueprint_client
from invenio_oauthclient.views.settings import blueprint as blueprint_settings
from invenio_mail import InvenioMail as Mail

# [ Configure application credentials ]
ORCID_APP_CREDENTIALS = dict(
Expand Down
116 changes: 116 additions & 0 deletions invenio_oauthclient/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2016 CERN.
#
# Invenio is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# Invenio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Invenio; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

"""Views for OAuth."""

from __future__ import absolute_import, print_function

from flask.ext.admin.contrib.sqla import ModelView
from flask_babelex import gettext as _
from wtforms.fields import TextAreaField

from .models import RemoteAccount, RemoteToken, UserIdentity


class RemoteAccountView(ModelView):
"""Flask-Admin view to manage remote accounts from invenio-oauthclient."""

can_view_details = True

column_list = (
'id',
'user_id',
'client_id',
'extra_data',
'tokens',
)

remote_account_columns = (
'id',
'user_id',
'client_id',
'extra_data',
)

column_searchable_list = column_sortable_list = remote_account_columns

column_filters = ('id', 'user_id', 'client_id',)

column_default_sort = ('id', True)

column_display_all_relations = True
inline_models = (RemoteToken,)

column_labels = {
'id': _('ID'),
'user_id': _('User ID'),
'client_id': _('Client ID'),
}


class RemoteTokenView(ModelView):
"""Flask-Admin view to manage remote tokens from invenio-oauthclient."""

can_view_details = True

column_list = (
'id_remote_account',
'token_type',
'access_token',
)

column_searchable_list = \
column_sortable_list = \
column_list

column_filters = (
'id_remote_account',
'token_type',
'secret',
)

form_columns = (
'remote_account',
'token_type',
'access_token',
'secret',
)

column_labels = {
'id_remote_account': _('ID Remote Account'),
}

form_overrides = {
'access_token': TextAreaField
}


remote_account_adminview = {
'model': RemoteAccount,
'modelview': RemoteAccountView,
'category': _('User Management')
}

remote_token_adminview = {
'model': RemoteToken,
'modelview': RemoteTokenView,
'category': _('User Management')
}

__all__ = ('remote_account_adminview', 'remote_token_adminview')
4 changes: 2 additions & 2 deletions invenio_oauthclient/contrib/orcid.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def account_setup(remote, token, resp):
# FIXME put these data in user profile!
# Fill user full name if not already set
# if user and not any([user.given_names, user.family_name]):
# # Query ORCID to get the real name
# Query ORCID to get the real name
# response = remote.get("{0}/orcid-bio".format(orcid),
# headers={'Accept':
# 'application/orcid+json'},
Expand All @@ -214,5 +214,5 @@ def account_setup(remote, token, resp):
#
# db.session.add(user)
#
# # Refresh user cache
# Refresh user cache
# current_user.reload()
3 changes: 2 additions & 1 deletion invenio_oauthclient/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
from flask_login import user_logged_out
from flask_oauthlib.client import OAuth as FlaskOAuth

from . import config
from invenio_oauthclient import config

from .handlers import authorized_default_handler, disconnect_handler, \
make_handler, make_token_getter, oauth_logout_handler

Expand Down
12 changes: 10 additions & 2 deletions invenio_oauthclient/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@
"""Models for storing access tokens and links between users and remote apps."""

from flask import current_app
from invenio_accounts.models import User
from invenio_db import db
from sqlalchemy.ext.mutable import MutableDict
from sqlalchemy_utils import JSONType
from sqlalchemy_utils.types.encrypted import EncryptedType

from invenio_accounts.models import User


def _secret_key():
"""Return secret key from current application."""
Expand Down Expand Up @@ -119,10 +118,18 @@ def delete(self):
with db.session.begin_nested():
db.session.delete(self)

def __repr__(self):
"""String representation for model."""
return str(self.id)


class RemoteToken(db.Model):
"""Storage for the access tokens for linked accounts."""

def __repr__(self):
"""String representation for model."""
return "{0.token_type} {0.access_token}".format(self)

__tablename__ = 'oauthclient_remotetoken'

#
Expand Down Expand Up @@ -232,4 +239,5 @@ class UserIdentity(db.Model):
db.Index('useridentity_id_user_method', id_user, method, unique=True),
)


__all__ = ('RemoteAccount', 'RemoteToken', 'UserIdentity')
8 changes: 3 additions & 5 deletions invenio_oauthclient/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,17 @@

"""Utility methods to help find, authenticate or register a remote user."""

from flask import current_app, request, after_this_request
from flask import after_this_request, current_app, request
from flask_security import login_user, logout_user
from flask_security.registerable import register_user
from flask_security.confirmable import requires_confirmation
from flask_security.registerable import register_user
from invenio_accounts.models import User
from invenio_db import db
from uritools import urisplit
from werkzeug.local import LocalProxy

from invenio_accounts.models import User

from .models import RemoteAccount, RemoteToken, UserIdentity


_security = LocalProxy(lambda: current_app.extensions['security'])

_datastore = LocalProxy(lambda: _security.datastore)
Expand Down
9 changes: 8 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
'Flask-OAuthlib>=0.6.0,<0.7', # quick fix for issue invenio#2158
'Flask-Security>=1.7.5',
'invenio-accounts>=1.0.0a6',
'invenio-db>=1.0.0a4',
'invenio-db>=1.0.0a9',
# FIXME
# 'invenio-upgrader>=0.1.0',
# FIXME new oauthlib release after 0.7.2 has some compatible problems with
Expand All @@ -87,6 +87,7 @@
'six>=1.7.2',
'sqlalchemy-utils>=0.31',
'uritools>=1.0.1',
'invenio-admin>=1.0.0a2'
]

packages = find_packages()
Expand Down Expand Up @@ -160,6 +161,12 @@ def run_tests(self):
'invenio_i18n.translations': [
'invenio_oauthclient = invenio_oauthclient',
],
'invenio_admin.views': [
'invenio_oauth_remote_account = '
'invenio_oauthclient.admin:remote_account_adminview',
'invenio_oauth_remote_token = '
'invenio_oauthclient.admin:remote_token_adminview',
]
},
extras_require=extras_require,
install_requires=install_requires,
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
from flask_mail import Mail
from flask_menu import Menu as FlaskMenu
from flask_oauthlib.client import OAuth as FlaskOAuth
from invenio_accounts import InvenioAccounts
from invenio_db import InvenioDB, db

from invenio_accounts import InvenioAccounts
from invenio_oauthclient import InvenioOAuthClient
from invenio_oauthclient.contrib.orcid import REMOTE_APP
from invenio_oauthclient.views.client import blueprint as blueprint_client
Expand Down
64 changes: 64 additions & 0 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2016 CERN.
#
# Invenio is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# Invenio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Invenio; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

"""Views for OAuth."""
from flask import Flask, url_for
from flask.ext.admin import Admin
from invenio_admin import InvenioAdmin
from invenio_db import db
from werkzeug.local import LocalProxy

from invenio_oauthclient import InvenioOAuthClient
from invenio_oauthclient.admin import RemoteAccountView, RemoteTokenView, \
remote_account_adminview, remote_token_adminview


def test_admin(app):
"""Test flask-admin interace."""
InvenioOAuthClient(app)

assert isinstance(remote_account_adminview, dict)
assert isinstance(remote_token_adminview, dict)

assert 'model' in remote_account_adminview
assert 'modelview' in remote_account_adminview
assert 'model' in remote_token_adminview
assert 'modelview' in remote_token_adminview

admin = Admin(app, name="Test")

user_model = remote_account_adminview.pop('model')
user_view = remote_account_adminview.pop('modelview')
admin.add_view(user_view(user_model, db.session,
**remote_account_adminview))

with app.app_context():
# create user and save url for testing
request_url = url_for("remoteaccount.index_view")

with app.app_context():
with app.test_client() as client:
res = client.get(
request_url,
follow_redirects=True
)
assert res.status_code == 200
# import ipdb; ipdb.set_trace()
assert 'Extra Data' in str(res.get_data())
assert 'Tokens' in str(res.get_data())
2 changes: 1 addition & 1 deletion tests/test_contrib_orcid.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
from flask import session, url_for
from flask_login import _create_identifier
from flask_security.utils import login_user
from invenio_accounts.models import User
from mock import MagicMock
from six.moves.urllib_parse import parse_qs, urlparse

from invenio_accounts.models import User
from invenio_oauthclient.contrib.orcid import account_info
from invenio_oauthclient.models import UserIdentity
from invenio_oauthclient.views.client import serializer
Expand Down

0 comments on commit 82b09a7

Please sign in to comment.