Skip to content

Commit

Permalink
Merge branch 'release/0.116.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
sloria committed Jul 6, 2017
2 parents ddda42b + 21f301f commit a545a03
Show file tree
Hide file tree
Showing 34 changed files with 3,003 additions and 3,410 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ before_install:
/tmp/varnish/usr/sbin/varnishd -n /tmp -p feature=+esi_disable_xml_check -p vmod_dir=/tmp/varnish/usr/lib/varnish/vmods -F -f $PROJECT_DIR/tests/test_files/varnish.vcl -a *:8080 > /dev/null & export VARNISH_PID=$!
fi
install:
- nvm install 0.12.4
- nvm use 0.12.4
- npm install -g [email protected]
- cd $PROJECT_DIR
- cp website/settings/local-travis.py website/settings/local.py
- cp api/base/settings/local-travis.py api/base/settings/local.py
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
Changelog
*********

0.116.0 (2017-07-05)
====================
- Allow Styling in Admin App Preprint Provider HTML Fields
- OSF side changes for new navbar
- Distinguish Staging Admin from Production Admin
- Create Scope to Get User Email Address
- Cachebust CSS assets

0.115.0 (2017-06-21)
====================

Expand Down
4 changes: 2 additions & 2 deletions README-docker-compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
## Docker Sync

Ubuntu: Skip install of docker-sync, fswatch, and unison. instead...
`cp docker-compose.ubuntu.yml docker-compose.override.yml`
`cp docker-compose.linux.yml docker-compose.override.yml`
Ignore future steps that start, stop, or wait for docker-sync

1. Install Docker Sync 0.3.5
Expand Down Expand Up @@ -171,7 +171,7 @@ Ubuntu: Skip install of docker-sync, fswatch, and unison. instead...
- Populate preprint providers:
- After resetting your database or with a new install you will need to populate the table of preprint providers. **You must have run migrations first.**
- `docker-compose run --rm web python -m scripts.update_taxonomies`
- `docker-compose run --rm web python -m scripts.populate_preprint_providers`
- `docker-compose run --rm web python manage.py populate_fake_preprint_providers`
- Populate citation styles
- Needed for api v2 citation style rendering.
- `docker-compose run --rm web python -m scripts.parse_citation_styles`
Expand Down
1 change: 1 addition & 0 deletions admin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ If you are manually testing functionality for permissions views, do not log in t
- Select the already existing OSF User you'd like to make an admin superuser with `user = OSFUser.objects.get(username=<[email protected]>)`
- Set that user to be a superuser and staff with `user.is_superuser = True` and `user.is_staff = True`
- Save your user with `user.save()`
- Commit the changes with `commit()`

3. Log in to the admin
- Visit the admin at `http://localhost:8001/`
Expand Down
8 changes: 5 additions & 3 deletions admin/preprint_providers/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,17 @@ def clean_advisory_board(self, *args, **kwargs):
return bleach.clean(
self.data.get('advisory_board'),
tags=['a', 'b', 'br', 'div', 'em', 'h2', 'h3', 'li', 'p', 'strong', 'ul'],
attributes=['class', 'href', 'title', 'target'],
attributes=['class', 'style', 'href', 'title', 'target'],
styles=['text-align', 'vertical-align'],
strip=True
)

def clean_description(self, *args, **kwargs):
return bleach.clean(
self.data.get('description'),
tags=['a', 'br', 'em', 'p', 'span', 'strong'],
attributes=['class', 'href', 'title', 'target'],
attributes=['class', 'style', 'href', 'title', 'target'],
styles=['text-align', 'vertical-align'],
strip=True
)

Expand All @@ -54,6 +56,6 @@ def clean_footer_links(self, *args, **kwargs):
self.data.get('footer_links'),
tags=['a', 'br', 'div', 'em', 'p', 'span', 'strong'],
attributes=['class', 'style', 'href', 'title', 'target'],
styles=['vertical-align'],
styles=['text-align', 'vertical-align'],
strip=True
)
6 changes: 2 additions & 4 deletions admin/static/js/pages/prereg-admin-page.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
var $ = require('jquery');
require('bootstrap');

require('osf-style');

var $osf = require('js/osfHelpers');
var osfLanguage = require('js/osfLanguage');

Expand All @@ -14,13 +12,13 @@ $(document).ready(function() {
$drafts.addClass('osf-box');

var $draft = $(this);
$draft.removeClass('osf-box');
$draft.removeClass('osf-box');
$draft.addClass('osf-box-lt');
});

$('.prereg-draft-save').click(function(e) {

var $draftElement = $(this).closest('.prereg-draft') ;
var $draftElement = $(this).closest('.prereg-draft') ;
var $form = $draftElement.find('.prereg-draft-form');
var data = {};
$.each($form.serializeArray(), function(_, item) {
Expand Down
43 changes: 43 additions & 0 deletions api/base/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,49 @@ def to_internal_value(self, data):
return self.field.to_internal_value(data)


class EmailScopeRequired(ser.Field):
"""
Skip field if USER_EMAIL scope is not present.
SKip field if requesting user != serialized user.
"""

def __init__(self, field, **kwargs):
super(EmailScopeRequired, self).__init__(**kwargs)
self.field = field
self.required = field.required
self.read_only = field.read_only

def get_attribute(self, instance):
request = self.context.get('request')
view = self.context.get('view')
if view and request and request.auth:
scopes = request.auth.attributes['accessTokenScope']
if 'osf.users.user_email' in scopes and request.user == view.get_user():
return self.field.get_attribute(instance)
raise SkipField

def bind(self, field_name, parent):
super(EmailScopeRequired, self).bind(field_name, parent)
self.field.bind(field_name, self)

def to_internal_value(self, data):
return self.field.to_internal_value(data)

def to_representation(self, value):
if getattr(self.field.root, 'child', None):
self.field.parent = self.field.root.child
else:
self.field.parent = self.field.root
return self.field.to_representation(value)

def to_esi_representation(self, value, envelope='data'):
if getattr(self.field.root, 'child', None):
self.field.parent = self.field.root.child
else:
self.field.parent = self.field.root
return self.field.to_esi_representation(value, envelope)


class HideIfRegistration(ser.Field):
"""
If node is a registration, this field will return None.
Expand Down
3 changes: 2 additions & 1 deletion api/users/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from api.base.serializers import (
JSONAPISerializer, LinksField, RelationshipField, DevOnly, IDField, TypeField, ListDictField,
DateByVersion,
DateByVersion, EmailScopeRequired,
)
from api.base.utils import absolute_reverse, get_user_auth

Expand All @@ -34,6 +34,7 @@ class UserSerializer(JSONAPISerializer):
timezone = HideIfDisabled(ser.CharField(required=False, help_text="User's timezone, e.g. 'Etc/UTC"))
locale = HideIfDisabled(ser.CharField(required=False, help_text="User's locale, e.g. 'en_US'"))
social = ListDictField(required=False)
email = EmailScopeRequired(ser.CharField(source='username', read_only=True))

links = HideIfDisabled(LinksField(
{
Expand Down
26 changes: 26 additions & 0 deletions api_tests/base/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,29 @@ def test_full_write_scope_can_read_guid_view_and_user_cannot_view_project(self,
assert_equal(res.location, redirect_url)
redirect_res = res.follow(auth='some_valid_token', auth_type='jwt', expect_errors=True)
assert_equal(redirect_res.status_code, 403)

@mock.patch('framework.auth.cas.CasClient.profile')
def test_user_email_scope_can_read_email(self, mock_user_info):
mock_user_info.return_value = self._scoped_response(['osf.users.user_email', 'osf.users.profile_read'])
url = api_v2_url('users/me/', base_route='/', base_prefix='v2/')
res = self.app.get(url, auth='some_valid_token', auth_type='jwt', expect_errors=True)
assert_equal(res.status_code, 200)
assert_equal(res.json['data']['attributes']['email'], self.user.username)

@mock.patch('framework.auth.cas.CasClient.profile')
def test_non_user_email_scope_cannot_read_email(self, mock_user_info):
mock_user_info.return_value = self._scoped_response(['osf.users.profile_read'])
url = api_v2_url('users/me/', base_route='/', base_prefix='v2/')
res = self.app.get(url, auth='some_valid_token', auth_type='jwt', expect_errors=True)
assert_equal(res.status_code, 200)
assert_not_in('email', res.json['data']['attributes'])
assert_not_in(self.user.username, res.json)

@mock.patch('framework.auth.cas.CasClient.profile')
def test_user_email_scope_cannot_read_other_email(self, mock_user_info):
mock_user_info.return_value = self._scoped_response(['osf.users.user_email', 'osf.users.profile_read'])
url = api_v2_url('users/{}/'.format(self.user2._id), base_route='/', base_prefix='v2/')
res = self.app.get(url, auth='some_valid_token', auth_type='jwt', expect_errors=True)
assert_equal(res.status_code, 200)
assert_not_in('email', res.json['data']['attributes'])
assert_not_in(self.user2.username, res.json)
Loading

0 comments on commit a545a03

Please sign in to comment.