def add_contributor_json(user, current_user=None, node=None): """ Generate a dictionary representation of a user, optionally including # projects shared with `current_user` :param User user: The user object to serialize :param User current_user : The user object for a different user, to calculate number of projects in common :return dict: A dict representing the serialized user data """ # get shared projects if current_user: n_projects_in_common = current_user.n_projects_in_common(user) else: n_projects_in_common = 0 current_employment = None education = None if user.jobs: current_employment = user.jobs[0]['institution'] if user.schools: education = user.schools[0]['institution'] contributor_json = { 'fullname': user.fullname, 'email': user.email, 'id': user._primary_key, 'employment': current_employment, 'education': education, 'n_projects_in_common': n_projects_in_common, 'registered': user.is_registered, 'active': user.is_active, 'profile_image_url': user.profile_image_url(size=settings.PROFILE_IMAGE_MEDIUM), 'profile_url': user.profile_url } if node: contributor_info = user.contributor_set.get(node=node.parent_node) contributor_json['permission'] = get_contributor_permissions( contributor_info, as_list=False) contributor_json['visible'] = contributor_info.visible return contributor_json
def add_contributor_json(user, current_user=None, node=None): """ Generate a dictionary representation of a user, optionally including # projects shared with `current_user` :param User user: The user object to serialize :param User current_user : The user object for a different user, to calculate number of projects in common :return dict: A dict representing the serialized user data """ # get shared projects if current_user: n_projects_in_common = current_user.n_projects_in_common(user) else: n_projects_in_common = 0 current_employment = None education = None if user.jobs: current_employment = user.jobs[0]['institution'] if user.schools: education = user.schools[0]['institution'] contributor_json = { 'fullname': user.fullname, 'email': user.email, 'id': user._primary_key, 'employment': current_employment, 'education': education, 'n_projects_in_common': n_projects_in_common, 'registered': user.is_registered, 'active': user.is_active, 'profile_image_url': user.profile_image_url(size=settings.PROFILE_IMAGE_MEDIUM), 'profile_url': user.profile_url } if node: contributor_info = user.contributor_set.get(node=node.parent_node) contributor_json['permission'] = get_contributor_permissions(contributor_info, as_list=False) contributor_json['visible'] = contributor_info.visible return contributor_json
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 """ contrib = None if isinstance(user, Contributor): contrib = user user = contrib.user fullname = user.display_full_name(node=node) ret = { 'id': str(user._id), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + '...' + fullname[-23:], 'profile_image_url': user.profile_image_url(size=settings.PROFILE_IMAGE_MEDIUM), 'active': user.is_active, } if node is not None: if admin: flags = { 'visible': False, 'permission': 'read', } else: is_contributor_obj = isinstance(contrib, Contributor) flags = { 'visible': contrib.visible if is_contributor_obj else node.contributor_set.filter(user=user, visible=True).exists(), 'permission': get_contributor_permissions(contrib, as_list=False) if is_contributor_obj else 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 ret.update({ 'activity_points': user.get_activity_points(), 'profile_image_url': user.profile_image_url(size=settings.PROFILE_IMAGE_LARGE), 'is_merged': user.is_merged, 'merged_by': merged_by, }) if include_node_counts: projects = user.nodes.exclude(is_deleted=True).filter( type='osf.node').get_roots() 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, 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 """ contrib = None if isinstance(user, Contributor): contrib = user user = contrib.user fullname = user.display_full_name(node=node) ret = { 'id': str(user._id), 'registered': user.is_registered, 'surname': user.family_name, 'fullname': fullname, 'shortname': fullname if len(fullname) < 50 else fullname[:23] + '...' + fullname[-23:], 'profile_image_url': user.profile_image_url(size=settings.PROFILE_IMAGE_MEDIUM), 'active': user.is_active, } if node is not None: if admin: flags = { 'visible': False, 'permission': 'read', } else: is_contributor_obj = isinstance(contrib, Contributor) flags = { 'visible': contrib.visible if is_contributor_obj else node.contributor_set.filter(user=user, visible=True).exists(), 'permission': get_contributor_permissions(contrib, as_list=False) if is_contributor_obj else 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 ret.update({ 'activity_points': user.get_activity_points(), 'profile_image_url': user.profile_image_url(size=settings.PROFILE_IMAGE_LARGE), 'is_merged': user.is_merged, 'merged_by': merged_by, }) if include_node_counts: projects = user.nodes.exclude(is_deleted=True).filter(type='osf.node').get_roots() ret.update({ 'number_projects': projects.count(), 'number_public_projects': projects.filter(is_public=True).count(), }) return ret
def _view_project(node, auth, primary=False, embed_contributors=False, embed_descendants=False, embed_registrations=False, embed_forks=False): """Build a JSON object containing everything needed to render project.view.mako. """ node = AbstractNode.objects.filter( pk=node.pk).include('contributor__user__guids').get() user = auth.user try: contributor = node.contributor_set.get(user=user) except Contributor.DoesNotExist: contributor = None parent = node.find_readable_antecedent(auth) if user: bookmark_collection = find_bookmark_collection(user) bookmark_collection_id = bookmark_collection._id in_bookmark_collection = bookmark_collection.linked_nodes.filter( pk=node.pk).exists() else: in_bookmark_collection = False bookmark_collection_id = '' view_only_link = auth.private_key or request.args.get('view_only', '').strip('/') anonymous = has_anonymous_link(node, auth) addons = list(node.get_addons()) widgets, configs, js, css = _render_addons(addons) redirect_url = node.url + '?view_only=None' node_linked_preprint = node.linked_preprint disapproval_link = '' if (node.is_pending_registration and node.has_permission(user, ADMIN)): disapproval_link = node.root.registration_approval.stashed_urls.get( user._id, {}).get('reject', '') if (node.is_pending_embargo and node.has_permission(user, ADMIN)): disapproval_link = node.root.embargo.stashed_urls.get(user._id, {}).get( 'reject', '') # Before page load callback; skip if not primary call if primary: for addon in addons: messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind='info', dismissible=False, trust=True) NodeRelation = apps.get_model('osf.NodeRelation') is_registration = node.is_registration data = { 'node': { 'disapproval_link': disapproval_link, 'id': node._primary_key, 'title': node.title, 'category': node.category_display, 'category_short': node.category, 'node_type': node.project_or_component, 'description': node.description or '', 'license': serialize_node_license_record(node.license), 'url': node.url, 'api_url': node.api_url, 'absolute_url': node.absolute_url, 'redirect_url': redirect_url, 'display_absolute_url': node.display_absolute_url, 'update_url': node.api_url_for('update_node'), 'in_dashboard': in_bookmark_collection, 'is_public': node.is_public, 'is_archiving': node.archiving, 'date_created': iso8601format(node.created), 'date_modified': iso8601format(node.last_logged) if node.last_logged else '', 'tags': list( node.tags.filter(system=False).values_list('name', flat=True)), 'children': node.nodes_active.exists(), 'child_exists': Node.objects.get_children(node, active=True).exists(), 'is_registration': is_registration, 'is_pending_registration': node.is_pending_registration if is_registration else False, 'is_retracted': node.is_retracted if is_registration else False, 'is_pending_retraction': node.is_pending_retraction if is_registration else False, 'retracted_justification': getattr(node.retraction, 'justification', None) if is_registration else None, 'date_retracted': iso8601format(getattr(node.retraction, 'date_retracted', None)) if is_registration else '', 'embargo_end_date': node.embargo_end_date.strftime('%A, %b %d, %Y') if is_registration and node.embargo_end_date else '', 'is_pending_embargo': node.is_pending_embargo if is_registration else False, 'is_embargoed': node.is_embargoed if is_registration else False, 'is_pending_embargo_termination': is_registration and node.is_embargoed and (node.embargo_termination_approval and node.embargo_termination_approval.is_pending_approval), 'registered_from_url': node.registered_from.url if is_registration else '', 'registered_date': iso8601format(node.registered_date) if is_registration else '', 'root_id': node.root._id if node.root else None, 'registered_meta': node.registered_meta, 'registered_schemas': serialize_meta_schemas(list(node.registered_schema.all())) if is_registration else False, 'is_fork': node.is_fork, 'forked_from_id': node.forked_from._primary_key if node.is_fork else '', 'forked_from_display_absolute_url': node.forked_from.display_absolute_url if node.is_fork else '', 'forked_date': iso8601format(node.forked_date) if node.is_fork else '', 'fork_count': node.forks.exclude(type='osf.registration').filter( is_deleted=False).count(), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'templated_count': node.templated_list.count(), 'linked_nodes_count': NodeRelation.objects.filter(child=node, is_node_link=True).exclude( parent__type='osf.collection').count(), 'anonymous': anonymous, 'comment_level': node.comment_level, 'has_comments': node.comment_set.exists(), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, 'institutions': get_affiliated_institutions(node) if node else [], 'has_draft_registrations': node.has_active_draft_registrations, 'is_preprint': node.is_preprint, 'has_moderated_preprint': node_linked_preprint.provider.reviews_workflow if node_linked_preprint else '', 'preprint_state': node_linked_preprint.machine_state if node_linked_preprint else '', 'preprint_word': node_linked_preprint.provider.preprint_word if node_linked_preprint else '', 'preprint_provider': { 'name': node_linked_preprint.provider.name, 'workflow': node_linked_preprint.provider.reviews_workflow } if node_linked_preprint else {}, 'is_preprint_orphan': node.is_preprint_orphan, 'has_published_preprint': node.preprints.filter( is_published=True).exists() if node else False, 'preprint_file_id': node.preprint_file._id if node.preprint_file else None, 'preprint_url': node.preprint_url }, 'parent_node': { 'exists': parent is not None, 'id': parent._primary_key if parent else '', 'title': parent.title if parent else '', 'category': parent.category_display if parent else '', 'url': parent.url if parent else '', 'api_url': parent.api_url if parent else '', 'absolute_url': parent.absolute_url if parent else '', 'registrations_url': parent.web_url_for('node_registrations') if parent else '', 'is_public': parent.is_public if parent else '', 'is_contributor': parent.is_contributor(user) if parent else '', 'can_view': parent.can_view(auth) if parent else False, }, 'user': { 'is_contributor': bool(contributor), 'is_admin': bool(contributor) and contributor.admin, 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': bool(contributor) and contributor.write and not node.is_registration, 'can_edit_tags': bool(contributor) and contributor.write, 'has_read_permissions': node.has_permission(user, READ), 'permissions': get_contributor_permissions(contributor, as_list=True) if contributor else [], 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': bool(contributor) or node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, contributor), 'dashboard_id': bookmark_collection_id, 'institutions': get_affiliated_institutions(user) if user else [], }, # TODO: Namespace with nested dicts 'addons_enabled': [each.short_name for each in addons], 'addons': configs, 'addon_widgets': widgets, 'addon_widget_js': js, 'addon_widget_css': css, 'node_categories': [{ 'value': key, 'display_name': value } for key, value in settings.NODE_CATEGORY_MAP.iteritems()] } if embed_contributors and not anonymous: data['node']['contributors'] = utils.serialize_visible_contributors( node) else: data['node']['contributors'] = list( node.contributors.values_list('guids___id', flat=True)) if embed_descendants: descendants, all_readable = _get_readable_descendants(auth=auth, node=node) data['user']['can_sort'] = all_readable data['node']['descendants'] = [ serialize_node_summary(node=each, auth=auth, primary=not node.has_node_link_to(each), show_path=False) for each in descendants ] if embed_registrations: data['node']['registrations'] = [ serialize_node_summary(node=each, auth=auth, show_path=False) for each in node.registrations_all.order_by('-registered_date'). exclude(is_deleted=True).annotate(nlogs=Count('logs')) ] if embed_forks: data['node']['forks'] = [ serialize_node_summary(node=each, auth=auth, show_path=False) for each in node.forks.exclude(type='osf.registration').exclude( is_deleted=True).order_by('-forked_date').annotate( nlogs=Count('logs')) ] return data
def _view_project(node, auth, primary=False, embed_contributors=False, embed_descendants=False, embed_registrations=False, embed_forks=False): """Build a JSON object containing everything needed to render project.view.mako. """ node = AbstractNode.objects.filter(pk=node.pk).include('contributor__user__guids').get() user = auth.user try: contributor = node.contributor_set.get(user=user) except Contributor.DoesNotExist: contributor = None parent = node.find_readable_antecedent(auth) if user: bookmark_collection = find_bookmark_collection(user) bookmark_collection_id = bookmark_collection._id in_bookmark_collection = bookmark_collection.guid_links.filter(_id=node._id).exists() else: in_bookmark_collection = False bookmark_collection_id = '' view_only_link = auth.private_key or request.args.get('view_only', '').strip('/') anonymous = has_anonymous_link(node, auth) addons = list(node.get_addons()) widgets, configs, js, css = _render_addons(addons) redirect_url = node.url + '?view_only=None' disapproval_link = '' if (node.is_pending_registration and node.has_permission(user, ADMIN)): disapproval_link = node.root.registration_approval.stashed_urls.get(user._id, {}).get('reject', '') if (node.is_pending_embargo and node.has_permission(user, ADMIN)): disapproval_link = node.root.embargo.stashed_urls.get(user._id, {}).get('reject', '') # Before page load callback; skip if not primary call if primary: for addon in addons: messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind='info', dismissible=False, trust=True) NodeRelation = apps.get_model('osf.NodeRelation') is_registration = node.is_registration data = { 'node': { 'disapproval_link': disapproval_link, 'id': node._primary_key, 'title': node.title, 'category': node.category_display, 'category_short': node.category, 'node_type': node.project_or_component, 'description': node.description or '', 'license': serialize_node_license_record(node.license), 'url': node.url, 'api_url': node.api_url, 'absolute_url': node.absolute_url, 'redirect_url': redirect_url, 'display_absolute_url': node.display_absolute_url, 'update_url': node.api_url_for('update_node'), 'in_dashboard': in_bookmark_collection, 'is_public': node.is_public, 'is_archiving': node.archiving, 'date_created': iso8601format(node.created), 'date_modified': iso8601format(node.last_logged) if node.last_logged else '', 'tags': list(node.tags.filter(system=False).values_list('name', flat=True)), 'children': node.nodes_active.exists(), 'child_exists': Node.objects.get_children(node, active=True).exists(), 'is_supplemental_project': node.has_linked_published_preprints, 'is_registration': is_registration, 'is_pending_registration': node.is_pending_registration if is_registration else False, 'is_retracted': node.is_retracted if is_registration else False, 'is_pending_retraction': node.is_pending_retraction if is_registration else False, 'retracted_justification': getattr(node.retraction, 'justification', None) if is_registration else None, 'date_retracted': iso8601format(getattr(node.retraction, 'date_retracted', None)) if is_registration else '', 'embargo_end_date': node.embargo_end_date.strftime('%A, %b %d, %Y') if is_registration and node.embargo_end_date else '', 'is_pending_embargo': node.is_pending_embargo if is_registration else False, 'is_embargoed': node.is_embargoed if is_registration else False, 'is_pending_embargo_termination': is_registration and node.is_embargoed and ( node.embargo_termination_approval and node.embargo_termination_approval.is_pending_approval ), 'registered_from_url': node.registered_from.url if is_registration else '', 'registered_date': iso8601format(node.registered_date) if is_registration else '', 'root_id': node.root._id if node.root else None, 'registered_meta': node.registered_meta, 'registered_schemas': serialize_meta_schemas(list(node.registered_schema.all())) if is_registration else False, 'is_fork': node.is_fork, 'is_collected': node.is_collected, 'collections': serialize_collections(node.collecting_metadata_list, auth), 'forked_from_id': node.forked_from._primary_key if node.is_fork else '', 'forked_from_display_absolute_url': node.forked_from.display_absolute_url if node.is_fork else '', 'forked_date': iso8601format(node.forked_date) if node.is_fork else '', 'fork_count': node.forks.exclude(type='osf.registration').filter(is_deleted=False).count(), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'templated_count': node.templated_list.count(), 'linked_nodes_count': NodeRelation.objects.filter(child=node, is_node_link=True).exclude(parent__type='osf.collection').count(), 'anonymous': anonymous, 'comment_level': node.comment_level, 'has_comments': node.comment_set.exists(), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, 'visible_preprints': serialize_preprints(node, user), 'institutions': get_affiliated_institutions(node) if node else [], 'has_draft_registrations': node.has_active_draft_registrations, 'access_requests_enabled': node.access_requests_enabled, 'storage_location': node.osfstorage_region.name, 'waterbutler_url': node.osfstorage_region.waterbutler_url, 'mfr_url': node.osfstorage_region.mfr_url }, 'parent_node': { 'exists': parent is not None, 'id': parent._primary_key if parent else '', 'title': parent.title if parent else '', 'category': parent.category_display if parent else '', 'url': parent.url if parent else '', 'api_url': parent.api_url if parent else '', 'absolute_url': parent.absolute_url if parent else '', 'registrations_url': parent.web_url_for('node_registrations', _guid=True) if parent else '', 'is_public': parent.is_public if parent else '', 'is_contributor': parent.is_contributor(user) if parent else '', 'can_view': parent.can_view(auth) if parent else False, }, 'user': { 'is_contributor': bool(contributor), 'is_admin': bool(contributor) and contributor.admin, 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': bool(contributor) and contributor.write and not node.is_registration, 'can_edit_tags': bool(contributor) and contributor.write, 'has_read_permissions': node.has_permission(user, READ), 'permissions': get_contributor_permissions(contributor, as_list=True) if contributor else [], 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': bool(contributor) or node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, contributor), 'dashboard_id': bookmark_collection_id, 'institutions': get_affiliated_institutions(user) if user else [], }, # TODO: Namespace with nested dicts 'addons_enabled': [each.short_name for each in addons], 'addons': configs, 'addon_widgets': widgets, 'addon_widget_js': js, 'addon_widget_css': css, 'node_categories': [ {'value': key, 'display_name': value} for key, value in settings.NODE_CATEGORY_MAP.items() ] } # Default should be at top of list for UI and for the project overview page the default region # for a component is that of the it's parent node. region_list = get_storage_region_list(user, node=node) data.update({'storage_regions': region_list}) data.update({'storage_flag_is_active': storage_i18n_flag_active()}) if embed_contributors and not anonymous: data['node']['contributors'] = utils.serialize_visible_contributors(node) else: data['node']['contributors'] = list(node.contributors.values_list('guids___id', flat=True)) if embed_descendants: descendants, all_readable = _get_readable_descendants(auth=auth, node=node) data['user']['can_sort'] = all_readable data['node']['descendants'] = [ serialize_node_summary(node=each, auth=auth, primary=not node.has_node_link_to(each), show_path=False) for each in descendants ] if embed_registrations: data['node']['registrations'] = [ serialize_node_summary(node=each, auth=auth, show_path=False) for each in node.registrations_all.order_by('-registered_date').exclude(is_deleted=True) ] if embed_forks: data['node']['forks'] = [ serialize_node_summary(node=each, auth=auth, show_path=False) for each in node.forks.exclude(type='osf.registration').exclude(is_deleted=True).order_by('-forked_date') ] return data