def test_reduce_permissions(): result = permissions.reduce_permissions(['read', 'write', 'admin']) assert_equal(result, 'admin') result2 = permissions.reduce_permissions(['read', 'write']) assert_equal(result2, 'write') result3 = permissions.reduce_permissions(['read']) assert_equal(result3, 'read')
def create(self, validated_data): auth = Auth(self.context['request'].user) node = self.context['view'].get_node() contributor = get_object_or_error(User, validated_data['_id'], display_name='user') # Node object checks for contributor existence but can still change permissions anyway if contributor in node.contributors: raise exceptions.ValidationError( '{} is already a contributor'.format(contributor.fullname)) bibliographic = validated_data['bibliographic'] permissions = osf_permissions.expand_permissions( validated_data.get('permission') ) or osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS node.add_contributor(contributor=contributor, auth=auth, visible=bibliographic, permissions=permissions, save=True) contributor.permission = osf_permissions.reduce_permissions( node.get_permissions(contributor)) contributor.bibliographic = node.get_visible(contributor) contributor.node_id = node._id return contributor
def update(self, instance, validated_data): index = None if 'index' in validated_data: index = validated_data.pop('index') contributor = instance auth = Auth(self.context['request'].user) node = self.context['view'].get_node() if 'bibliographic' in validated_data: bibliographic = validated_data.get('bibliographic') else: bibliographic = node.get_visible(contributor) permission = validated_data.get('permission') or contributor.permission try: if index is not None: node.move_contributor(contributor, auth, index, save=True) node.update_contributor(contributor, permission, bibliographic, auth, save=True) except NodeStateError as e: raise exceptions.ValidationError(detail=e.message) except ValueError as e: raise exceptions.ValidationError(detail=e.message) contributor.permission = osf_permissions.reduce_permissions(node.get_permissions(contributor)) contributor.bibliographic = node.get_visible(contributor) contributor.node_id = node._id if index is not None: contributor.index = index return contributor
def _render_node(node, auth=None): """ :param node: :return: """ perm = None # NOTE: auth.user may be None if viewing public project while not # logged in if auth and auth.user and node.get_permissions(auth.user): perm_list = node.get_permissions(auth.user) perm = permissions.reduce_permissions(perm_list) return { "title": node.title, "id": node._primary_key, "url": node.url, "api_url": node.api_url, "primary": node.primary, "date_modified": utils.iso8601format(node.date_modified), "category": node.category, "permissions": perm, # A string, e.g. 'admin', or None, "archiving": node.archiving, }
def update(self, instance, validated_data): index = None if 'index' in validated_data: index = validated_data.pop('index') contributor = instance auth = Auth(self.context['request'].user) node = self.context['view'].get_node() if 'bibliographic' in validated_data: bibliographic = validated_data.get('bibliographic') else: bibliographic = node.get_visible(contributor) permission = validated_data.get('permission') or contributor.permission try: if index is not None: node.move_contributor(contributor, auth, index, save=True) node.update_contributor(contributor, permission, bibliographic, auth, save=True) except NodeStateError as e: raise exceptions.ValidationError(detail=e.message) except ValueError as e: raise exceptions.ValidationError(detail=e.message) contributor.permission = osf_permissions.reduce_permissions( node.get_permissions(contributor)) contributor.bibliographic = node.get_visible(contributor) contributor.node_id = node._id if index is not None: contributor.index = index return contributor
def serialize_simple_user(user_info): user = User.load(user_info[0]) return { 'id': user._id, 'name': user.fullname, 'permission': reduce_permissions(user_info[1]) if user_info[1] else None, }
def _render_node(node, auth=None): """ :param node: :return: """ perm = None # NOTE: auth.user may be None if viewing public project while not # logged in if auth and auth.user and node.get_permissions(auth.user): perm_list = node.get_permissions(auth.user) perm = permissions.reduce_permissions(perm_list) return { 'title': node.title, 'id': node._primary_key, 'url': node.url, 'api_url': node.api_url, 'primary': node.primary, 'date_modified': utils.iso8601format(node.date_modified), 'category': node.category, 'permissions': perm, # A string, e.g. 'admin', or None, 'archiving': node.archiving, }
def serialize_user(user, node=None, full=False): """Return a dictionary representation of a registered user. :param User user: A User object :param bool full: Include complete user properties """ fullname = user.display_full_name(node=node) rv = { 'id': str(user._primary_key), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + "..." + fullname[-23:], 'gravatar_url': gravatar( user, use_ssl=True, size=settings.GRAVATAR_SIZE_ADD_CONTRIBUTOR ), 'active': user.is_active(), } if node is not None: rv.update({ 'visible': user._id in node.visible_contributor_ids, 'permission': reduce_permissions(node.get_permissions(user)), }) if user.is_registered: rv.update({ 'url': user.url, 'absolute_url': user.absolute_url, 'display_absolute_url': user.display_absolute_url, 'date_registered': user.date_registered.strftime("%Y-%m-%d"), }) if full: if user.is_merged: merger = user.merged_by merged_by = { 'id': str(merger._primary_key), 'url': merger.url, 'absolute_url': merger.absolute_url } else: merged_by = None rv.update({ 'number_projects': len(get_projects(user)), 'number_public_projects': len(get_public_projects(user)), 'activity_points': user.get_activity_points(), 'gravatar_url': gravatar( user, use_ssl=True, size=settings.GRAVATAR_SIZE_PROFILE ), 'is_merged': user.is_merged, 'merged_by': merged_by, }) return rv
class NodeContributorsSerializer(JSONAPISerializer): """ Separate from UserSerializer due to necessity to override almost every field as read only """ non_anonymized_fields = ['bibliographic', 'permission'] filterable_fields = frozenset( ['id', 'bibliographic', 'permission', 'index']) id = IDField(source='_id', read_only=True) type = TypeField() index = ser.IntegerField(required=False, read_only=True, source='_order') bibliographic = ser.BooleanField( help_text= 'Whether the user will be included in citations for this node or not.', default=True) permission = ser.ChoiceField( choices=osf_permissions.PERMISSIONS, required=False, allow_null=True, default=osf_permissions.reduce_permissions( osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS), help_text= 'User permission level. Must be "read", "write", or "admin". Defaults to "write".' ) unregistered_contributor = ser.SerializerMethodField() links = LinksField({'self': 'get_absolute_url'}) users = RelationshipField(related_view='users:user-detail', related_view_kwargs={'user_id': '<user._id>'}, always_embed=True) node = RelationshipField(related_view='nodes:node-detail', related_view_kwargs={'node_id': '<node._id>'}) class Meta: type_ = 'contributors' def get_absolute_url(self, obj): return absolute_reverse( 'nodes:node-contributor-detail', kwargs={ 'user_id': obj.user._id, 'node_id': self.context['request'].parser_context['kwargs']['node_id'], 'version': self.context['request'].parser_context['kwargs']['version'] }) def get_unregistered_contributor(self, obj): unclaimed_records = obj.user.unclaimed_records.get(obj.node._id, None) if unclaimed_records: return unclaimed_records.get('name', None)
def create(self, validated_data): auth = Auth(self.context['request'].user) node = self.context['view'].get_node() contributor = get_object_or_error(User, validated_data['_id'], display_name='user') # Node object checks for contributor existence but can still change permissions anyway if contributor in node.contributors: raise exceptions.ValidationError('{} is already a contributor'.format(contributor.fullname)) bibliographic = validated_data['bibliographic'] permissions = osf_permissions.expand_permissions(validated_data.get('permission')) or osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS node.add_contributor(contributor=contributor, auth=auth, visible=bibliographic, permissions=permissions, save=True) contributor.permission = osf_permissions.reduce_permissions(node.get_permissions(contributor)) contributor.bibliographic = node.get_visible(contributor) contributor.node_id = node._id return contributor
def update(self, instance, validated_data): contributor = instance auth = Auth(self.context['request'].user) node = self.context['view'].get_node() visible = validated_data.get('bibliographic') permission = validated_data.get('permission') try: node.update_contributor(contributor, permission, visible, auth, save=True) except NodeStateError as e: raise exceptions.ValidationError(e) contributor.permission = osf_permissions.reduce_permissions(node.get_permissions(contributor)) contributor.bibliographic = node.get_visible(contributor) contributor.node_id = node._id return contributor
class NodeContributorsSerializer(JSONAPISerializer): """ Separate from UserSerializer due to necessity to override almost every field as read only """ filterable_fields = frozenset([ 'id', 'bibliographic', 'permission' ]) id = IDField(source='_id', required=True) type = TypeField() bibliographic = ser.BooleanField(help_text='Whether the user will be included in citations for this node or not.', default=True) permission = ser.ChoiceField(choices=osf_permissions.PERMISSIONS, required=False, allow_null=True, default=osf_permissions.reduce_permissions(osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS), help_text='User permission level. Must be "read", "write", or "admin". Defaults to "write".') links = LinksField({ 'self': 'get_absolute_url' }) users = RelationshipField( related_view='users:user-detail', related_view_kwargs={'user_id': '<pk>'}, always_embed=True ) class Meta: type_ = 'contributors' def absolute_url(self, obj): return obj.absolute_url def get_absolute_url(self, obj): node_id = self.context['request'].parser_context['kwargs']['node_id'] return absolute_reverse( 'nodes:node-contributor-detail', kwargs={ 'node_id': node_id, 'user_id': obj._id } )
def _render_node(node, user=None): """ :param node: :return: """ perm = None if user: perm_list = node.get_permissions(user) perm = permissions.reduce_permissions(perm_list) return { 'title': node.title, 'id': node._primary_key, 'url': node.url, 'api_url': node.api_url, 'primary': node.primary, 'date_modified': utils.iso8601format(node.date_modified), 'category': node.category, 'permissions': perm, # A string, e.g. 'admin', or None }
def test_reduce_permissions_with_unknown_permission_raises_error(): with assert_raises(ValueError): permissions.reduce_permissions(['unknownpermission'])
def test_reduce_permissions_with_empty_list_raises_error(): with assert_raises(ValueError): permissions.reduce_permissions([])
class NodeContributorsSerializer(JSONAPISerializer): """ Separate from UserSerializer due to necessity to override almost every field as read only """ filterable_fields = frozenset([ 'fullname', 'given_name', 'middle_name', 'family_name', 'id', 'bibliographic', 'permissions' ]) id = ser.CharField(source='_id', label='ID') fullname = ser.CharField( read_only=True, help_text='Display name used in the general user interface') given_name = ser.CharField(read_only=True, help_text='For bibliographic citations') middle_name = ser.CharField(read_only=True, source='middle_names', help_text='For bibliographic citations') family_name = ser.CharField(read_only=True, help_text='For bibliographic citations') suffix = ser.CharField(read_only=True, help_text='For bibliographic citations') date_registered = ser.DateTimeField(read_only=True) profile_image_url = ser.SerializerMethodField(required=False, read_only=True) def get_profile_image_url(self, user): size = self.context['request'].query_params.get('profile_image_size') return user.profile_image_url(size=size) bibliographic = ser.BooleanField( help_text= 'Whether the user will be included in citations for this node or not.', default=True) permission = ser.ChoiceField( choices=osf_permissions.PERMISSIONS, required=False, allow_null=True, default=osf_permissions.reduce_permissions( osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS), help_text= 'User permission level. Must be "read", "write", or "admin". Defaults to "write".' ) links = LinksField({'html': 'absolute_url'}) nodes = JSONAPIHyperlinkedIdentityField(view_name='users:user-nodes', lookup_field='pk', lookup_url_kwarg='user_id', link_type='related') class Meta: type_ = 'users' def absolute_url(self, obj): return obj.absolute_url def get_absolute_url(self, obj): node_id = self.context['request'].parser_context['kwargs']['node_id'] return absolute_reverse('nodes:node-contributor-detail', kwargs={ 'node_id': node_id, 'user_id': obj._id }) def create(self, validated_data): auth = Auth(self.context['request'].user) node = self.context['view'].get_node() contributor = get_object_or_error(User, validated_data['_id'], display_name='user') # Node object checks for contributor existence but can still change permissions anyway if contributor in node.contributors: raise exceptions.ValidationError( '{} is already a contributor'.format(contributor.fullname)) bibliographic = validated_data['bibliographic'] permissions = osf_permissions.expand_permissions( validated_data.get('permission') ) or osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS node.add_contributor(contributor=contributor, auth=auth, visible=bibliographic, permissions=permissions, save=True) contributor.permission = osf_permissions.reduce_permissions( node.get_permissions(contributor)) contributor.bibliographic = node.get_visible(contributor) contributor.node_id = node._id return contributor
def serialize_user(user, node=None, admin=False, full=False, is_profile=False, include_node_counts=False): """ Return a dictionary representation of a registered user. :param User user: A User object :param bool full: Include complete user properties """ from website.project.utils import PROJECT_QUERY contrib = None if isinstance(user, Contributor): contrib = user user = contrib.user fullname = user.display_full_name(node=node) ret = { 'id': str(user._primary_key), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + '...' + fullname[-23:], 'gravatar_url': gravatar( user, use_ssl=True, size=settings.PROFILE_IMAGE_MEDIUM ), 'active': user.is_active, } if node is not None: if admin: flags = { 'visible': False, 'permission': 'read', } else: flags = { 'visible': contrib.visible if isinstance(contrib, Contributor) else node.contributor_set.filter(user=user, visible=True).exists(), 'permission': reduce_permissions(node.get_permissions(user)), } ret.update(flags) if user.is_registered: ret.update({ 'url': user.url, 'absolute_url': user.absolute_url, 'display_absolute_url': user.display_absolute_url, 'date_registered': user.date_registered.strftime('%Y-%m-%d'), }) if full: # Add emails if is_profile: ret['emails'] = [ { 'address': each, 'primary': each.strip().lower() == user.username.strip().lower(), 'confirmed': True, } for each in user.emails ] + [ { 'address': each, 'primary': each.strip().lower() == user.username.strip().lower(), 'confirmed': False } for each in user.get_unconfirmed_emails_exclude_external_identity() ] if user.is_merged: merger = user.merged_by merged_by = { 'id': str(merger._primary_key), 'url': merger.url, 'absolute_url': merger.absolute_url } else: merged_by = None projects = Node.find_for_user(user, PROJECT_QUERY).get_roots() ret.update({ 'activity_points': user.get_activity_points(), 'gravatar_url': gravatar( user, use_ssl=True, size=settings.PROFILE_IMAGE_LARGE ), 'is_merged': user.is_merged, 'merged_by': merged_by, }) if include_node_counts: ret.update({ 'number_projects': projects.count(), 'number_public_projects': projects.filter(is_public=True).count(), }) return ret
def serialize_user(user, node=None, admin=False, full=False, is_profile=False): """ Return a dictionary representation of a registered user. :param User user: A User object :param bool full: Include complete user properties """ fullname = user.display_full_name(node=node) ret = { 'id': str(user._primary_key), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + "..." + fullname[-23:], 'gravatar_url': gravatar( user, use_ssl=True, size=settings.PROFILE_IMAGE_MEDIUM ), 'active': user.is_active, } if node is not None: if admin: flags = { 'visible': False, 'permission': 'read', } else: flags = { 'visible': user._id in node.visible_contributor_ids, 'permission': reduce_permissions(node.get_permissions(user)), } ret.update(flags) if user.is_registered: ret.update({ 'url': user.url, 'absolute_url': user.absolute_url, 'display_absolute_url': user.display_absolute_url, 'date_registered': user.date_registered.strftime("%Y-%m-%d"), }) if full: # Add emails if is_profile: ret['emails'] = [ { 'address': each, 'primary': each.strip().lower() == user.username.strip().lower(), 'confirmed': True, } for each in user.emails ] + [ { 'address': each, 'primary': each.strip().lower() == user.username.strip().lower(), 'confirmed': False } for each in user.unconfirmed_emails ] if user.is_merged: merger = user.merged_by merged_by = { 'id': str(merger._primary_key), 'url': merger.url, 'absolute_url': merger.absolute_url } else: merged_by = None ret.update({ 'number_projects': get_projects(user).count(), 'number_public_projects': get_public_projects(user).count(), 'activity_points': user.get_activity_points(), 'gravatar_url': gravatar( user, use_ssl=True, size=settings.PROFILE_IMAGE_LARGE ), 'is_merged': user.is_merged, 'merged_by': merged_by, }) return ret
def serialize_simple_user_and_node_permissions(node, user): return { 'id': user._id, 'name': user.fullname, 'permission': reduce_permissions(node.get_permissions(user)) }
def serialize_user(user, node=None, admin=False, full=False): """ Return a dictionary representation of a registered user. :param User user: A User object :param bool full: Include complete user properties """ fullname = user.display_full_name(node=node) ret = { 'id': str(user._primary_key), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + "..." + fullname[-23:], 'gravatar_url': gravatar(user, use_ssl=True, size=settings.GRAVATAR_SIZE_ADD_CONTRIBUTOR), 'active': user.is_active, } if node is not None: if admin: flags = { 'visible': False, 'permission': 'read', } else: flags = { 'visible': user._id in node.visible_contributor_ids, 'permission': reduce_permissions(node.get_permissions(user)), } ret.update(flags) if user.is_registered: ret.update({ 'url': user.url, 'absolute_url': user.absolute_url, 'display_absolute_url': user.display_absolute_url, 'date_registered': user.date_registered.strftime("%Y-%m-%d"), }) if full: # Add emails ret['emails'] = [{ 'address': each, 'primary': each == user.username, 'confirmed': True, } for each in user.emails] + [{ 'address': each, 'primary': each == user.username, 'confirmed': False } for each in user.unconfirmed_emails] if user.is_merged: merger = user.merged_by merged_by = { 'id': str(merger._primary_key), 'url': merger.url, 'absolute_url': merger.absolute_url } else: merged_by = None ret.update({ 'number_projects': len(get_projects(user)), 'number_public_projects': len(get_public_projects(user)), 'activity_points': user.get_activity_points(), 'gravatar_url': gravatar(user, use_ssl=True, size=settings.GRAVATAR_SIZE_PROFILE), 'is_merged': user.is_merged, 'merged_by': merged_by, }) return ret
def serialize_user(user, node=None, admin=False, full=False, is_profile=False, include_node_counts=False): """ Return a dictionary representation of a registered user. :param User user: A User object :param bool full: Include complete user properties """ from website.project.utils import PROJECT_QUERY contrib = None if isinstance(user, Contributor): contrib = user user = contrib.user fullname = user.display_full_name(node=node) ret = { 'id': str(user._primary_key), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + '...' + fullname[-23:], 'gravatar_url': gravatar( user, use_ssl=True, size=settings.PROFILE_IMAGE_MEDIUM ), 'active': user.is_active, } if node is not None: if admin: flags = { 'visible': False, 'permission': 'read', } else: flags = { 'visible': contrib.visible if isinstance(contrib, Contributor) else node.contributor_set.filter(user=user, visible=True).exists(), 'permission': reduce_permissions(node.get_permissions(user)), } ret.update(flags) if user.is_registered: ret.update({ 'url': user.url, 'absolute_url': user.absolute_url, 'display_absolute_url': user.display_absolute_url, 'date_registered': user.date_registered.strftime('%Y-%m-%d'), }) if full: # Add emails if is_profile: ret['emails'] = [ { 'address': each, 'primary': each.strip().lower() == user.username.strip().lower(), 'confirmed': True, } for each in user.emails.values_list('address', flat=True) ] + [ { 'address': each, 'primary': each.strip().lower() == user.username.strip().lower(), 'confirmed': False } for each in user.get_unconfirmed_emails_exclude_external_identity() ] if user.is_merged: merger = user.merged_by merged_by = { 'id': str(merger._primary_key), 'url': merger.url, 'absolute_url': merger.absolute_url } else: merged_by = None projects = Node.find_for_user(user, PROJECT_QUERY).get_roots() ret.update({ 'activity_points': user.get_activity_points(), 'gravatar_url': gravatar( user, use_ssl=True, size=settings.PROFILE_IMAGE_LARGE ), 'is_merged': user.is_merged, 'merged_by': merged_by, }) if include_node_counts: ret.update({ 'number_projects': projects.count(), 'number_public_projects': projects.filter(is_public=True).count(), }) return ret