def get_contributors(auth, node, **kwargs): # Can set limit to only receive a specified number of contributors in a call to this route if request.args.get('limit'): try: limit = int(request.args['limit']) except ValueError: raise HTTPError(http.BAD_REQUEST, data=dict( message_long='Invalid value for "limit": {}'.format(request.args['limit']) )) else: limit = None anonymous = has_anonymous_link(node, auth) if anonymous or not node.can_view(auth): raise HTTPError(http.FORBIDDEN) # Limit is either an int or None: # if int, contribs list is sliced to specified length # if None, contribs list is not sliced contribs = profile_utils.serialize_contributors( node.visible_contributors[0:limit], node=node, ) # Will either return just contributor list or contributor list + 'more' element if limit: return { 'contributors': contribs, 'more': max(0, len(node.visible_contributors) - limit) } else: return {'contributors': contribs}
def _get_logs(node, count, auth, link=None, page=0): """ :param Node node: :param int count: :param auth: :return list: List of serialized logs, boolean: if there are more logs """ logs = [] total = 0 for log in reversed(node.logs): # A number of errors due to database inconsistency can arise here. The # log can be None; its `node__logged` back-ref can be empty, and the # 0th logged node can be None. Need to make sure that log is not None if log: log_node = log.resolve_node(node) if log.can_view(node, auth): total += 1 anonymous = has_anonymous_link(log_node, auth) logs.append(serialize_log(log, anonymous)) else: logger.warn('Log on node {} is None'.format(node._id)) paginated_logs, pages = paginate(logs, total, page, count) return list(paginated_logs), total, pages
def _get_summary(node, auth, rescale_ratio, primary=True, link_id=None, show_path=False): # TODO(sloria): Refactor this or remove (lots of duplication with _view_project) summary = { 'id': link_id if link_id else node._id, 'primary': primary, 'is_registration': node.is_registration, 'is_fork': node.is_fork, 'is_pending_registration': node.is_pending_registration, 'is_retracted': node.is_retracted, 'is_pending_retraction': node.is_pending_retraction, 'embargo_end_date': node.embargo_end_date.strftime("%A, %b. %d, %Y") if node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo, 'archiving': node.archiving, } if node.can_view(auth): summary.update({ 'can_view': True, 'can_edit': node.can_edit(auth), 'primary_id': node._id, 'url': node.url, 'primary': primary, 'api_url': node.api_url, 'title': node.title, 'category': node.category, 'node_type': node.project_or_component, 'is_fork': node.is_fork, 'is_registration': node.is_registration, 'anonymous': has_anonymous_link(node, auth), 'registered_date': node.registered_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_registration else None, 'forked_date': node.forked_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_fork else None, 'nlogs': None, 'ua_count': None, 'ua': None, 'non_ua': None, 'addons_enabled': node.get_addon_names(), 'is_public': node.is_public, 'parent_title': node.parent_node.title if node.parent_node else None, 'parent_is_public': node.parent_node.is_public if node.parent_node else False, 'show_path': show_path }) if rescale_ratio: ua_count, ua, non_ua = _get_user_activity(node, auth, rescale_ratio) summary.update({ 'nlogs': len(node.logs), 'ua_count': ua_count, 'ua': ua, 'non_ua': non_ua, }) else: summary['can_view'] = False # TODO: Make output format consistent with _view_project return { 'summary': summary, }
def node_register_template_page(auth, node, metaschema_id, **kwargs): if node.is_registration and bool(node.registered_schema): try: meta_schema = RegistrationSchema.objects.get(_id=metaschema_id) except RegistrationSchema.DoesNotExist: # backwards compatability for old urls, lookup by name meta_schema = RegistrationSchema.objects.filter(name=_id_to_name(metaschema_id)).order_by('-schema_version').first() if not meta_schema: raise HTTPError(http.NOT_FOUND, data={ 'message_short': 'Invalid schema name', 'message_long': 'No registration schema with that name could be found.' }) if not node.registered_schema.filter(id=meta_schema.id).exists(): raise HTTPError(http.BAD_REQUEST, data={ 'message_short': 'Invalid schema', 'message_long': 'This registration has no registration supplment with that name.' }) ret = _view_project(node, auth, primary=True) my_meta = serialize_meta_schema(meta_schema) if has_anonymous_link(node, auth): for indx, schema_page in enumerate(my_meta['schema']['pages']): for idx, schema_question in enumerate(schema_page['questions']): if schema_question['title'] in settings.ANONYMIZED_TITLES: del my_meta['schema']['pages'][indx]['questions'][idx] ret['node']['registered_schema'] = serialize_meta_schema(meta_schema) return ret else: status.push_status_message( 'You have been redirected to the project\'s registrations page. From here you can initiate a new Draft Registration to complete the registration process', trust=False, id='redirected_to_registrations', ) return redirect(node.web_url_for('node_registrations', view=kwargs.get('template'), _guid=True))
def comment_discussion(auth, node, **kwargs): users = collect_discussion(node) anonymous = has_anonymous_link(node, auth) # Sort users by comment frequency # TODO: Allow sorting by recency, combination of frequency and recency sorted_users = sorted( users.keys(), key=lambda item: len(users[item]), reverse=True, ) return { 'discussion': [ { 'id': privacy_info_handle(user._id, anonymous), 'url': privacy_info_handle(user.url, anonymous), 'fullname': privacy_info_handle(user.fullname, anonymous, name=True), 'isContributor': node.is_contributor(user), 'gravatarUrl': privacy_info_handle( gravatar( user, use_ssl=True, size=settings.GRAVATAR_SIZE_DISCUSSION, ), anonymous ), } for user in sorted_users ] }
def get_node_contributors_abbrev(auth, node, **kwargs): anonymous = has_anonymous_link(node, auth) formatter = "surname" max_count = kwargs.get("max_count", 3) if "user_ids" in kwargs: users = [User.load(user_id) for user_id in kwargs["user_ids"] if user_id in node.visible_contributor_ids] else: users = node.visible_contributors if anonymous or not node.can_view(auth): raise HTTPError(http.FORBIDDEN) contributors = [] n_contributors = len(users) others_count = "" for index, user in enumerate(users[:max_count]): if index == max_count - 1 and len(users) > max_count: separator = " &" others_count = str(n_contributors - 3) elif index == len(users) - 1: separator = "" elif index == len(users) - 2: separator = " &" else: separator = "," contributor = user.get_summary(formatter) contributor["user_id"] = user._primary_key contributor["separator"] = separator contributors.append(contributor) return {"contributors": contributors, "others_count": others_count}
def _get_logs(node, count, auth, link=None, offset=0): """ :param Node node: :param int count: :param auth: :return list: List of serialized logs, boolean: if there are more logs """ logs = [] has_more_logs = False for log in (x for idx, x in enumerate(reversed(node.logs)) if idx >= offset): # A number of errors due to database inconsistency can arise here. The # log can be None; its `node__logged` back-ref can be empty, and the # 0th logged node can be None. Catch and log these errors and ignore # the offending logs. log_node = log.resolve_node(node) if log.can_view(node, auth): anonymous = has_anonymous_link(log_node, auth) if len(logs) < count: logs.append(serialize_log(log, anonymous)) else: has_more_logs = True break return logs, has_more_logs
def osf_storage_get_revisions(payload, node_addon, **kwargs): node = node_addon.owner page = payload.get('page') or 0 path = payload.get('path') is_anon = has_anonymous_link(node, Auth(private_key=payload.get('view_only'))) if not path: raise HTTPError(httplib.BAD_REQUEST) try: page = int(page) except (TypeError, ValueError): raise HTTPError(httplib.BAD_REQUEST) record = model.OsfStorageFileRecord.find_by_path(path, node_addon) if record is None: raise HTTPError(httplib.NOT_FOUND) indices, versions, more = record.get_versions( page, size=osf_storage_settings.REVISIONS_PAGE_SIZE, ) return { 'revisions': [ utils.serialize_revision(node, record, versions[idx], indices[idx], anon=is_anon) for idx in range(len(versions)) ], 'more': more, }
def dataverse_get_file_info(node_addon, auth, **kwargs): """API view that gets info for a file.""" node = node_addon.owner file_id = kwargs.get('path') fail_if_unauthorized(node_addon, auth, file_id) fail_if_private(file_id) anonymous = has_anonymous_link(node, auth) download_url = node.web_url_for('dataverse_download_file', path=file_id) dataverse_url = 'http://{0}/dvn/dv/'.format(HOST) + node_addon.dataverse_alias study_url = 'http://dx.doi.org/' + node_addon.study_hdl delete_url = node.api_url_for('dataverse_delete_file', path=file_id) data = { 'node': { 'id': node._id, 'title': node.title }, 'filename': scrape_dataverse(file_id, name_only=True)[0], 'dataverse': privacy_info_handle(node_addon.dataverse, anonymous), 'study': privacy_info_handle(node_addon.study, anonymous), 'urls': { 'dataverse': privacy_info_handle(dataverse_url, anonymous), 'study': privacy_info_handle(study_url, anonymous), 'download': privacy_info_handle(download_url, anonymous), 'delete': privacy_info_handle(delete_url, anonymous), 'files': node.web_url_for('collect_file_trees'), } } return {'data': data}, httplib.OK
def serialize_node_summary(node, auth, primary=True, show_path=False): summary = { 'id': node._id, 'primary': primary, 'is_registration': node.is_registration, 'is_fork': node.is_fork, 'is_pending_registration': node.is_pending_registration, 'is_retracted': node.is_retracted, 'is_pending_retraction': node.is_pending_retraction, 'embargo_end_date': node.embargo_end_date.strftime('%A, %b. %d, %Y') if node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo, 'is_embargoed': node.is_embargoed, 'archiving': node.archiving, } contributor_data = serialize_contributors_for_summary(node) parent_node = node.parent_node user = auth.user if node.can_view(auth): summary.update({ 'can_view': True, 'can_edit': node.can_edit(auth), 'primary_id': node._id, 'url': node.url, 'primary': primary, 'api_url': node.api_url, 'title': node.title, 'category': node.category, 'isPreprint': bool(node.preprint_file_id), 'childExists': bool(node.nodes_active), 'is_admin': node.has_permission(user, permissions.ADMIN), 'is_contributor': node.is_contributor(user), 'logged_in': auth.logged_in, 'node_type': node.project_or_component, 'is_fork': node.is_fork, 'is_registration': node.is_registration, 'anonymous': has_anonymous_link(node, auth), 'registered_date': node.registered_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_registration else None, 'forked_date': node.forked_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_fork else None, 'ua_count': None, 'ua': None, 'non_ua': None, 'is_public': node.is_public, 'parent_title': parent_node.title if parent_node else None, 'parent_is_public': parent_node.is_public if parent_node else False, 'show_path': show_path, # Read nlogs annotation if possible 'nlogs': node.nlogs if hasattr(node, 'nlogs') else node.logs.count(), 'contributors': contributor_data['contributors'], 'others_count': contributor_data['others_count'], }) else: summary['can_view'] = False return summary
def osfstorage_get_revisions(file_node, node_addon, payload, **kwargs): is_anon = has_anonymous_link(node_addon.owner, Auth(private_key=request.args.get('view_only'))) # Return revisions in descending order return { 'revisions': [ utils.serialize_revision(node_addon.owner, file_node, version, index=len(file_node.versions) - idx - 1, anon=is_anon) for idx, version in enumerate(reversed(file_node.versions)) ] }
def file_info(auth, fid, **kwargs): versions = [] node = kwargs['node'] or kwargs['project'] file_name = fid file_name_clean = urlsafe_filename(file_name) files_page_url = node.web_url_for('collect_file_trees') latest_download_url = None api_url = None anonymous = has_anonymous_link(node, auth) try: files_versions = node.files_versions[file_name_clean] except KeyError: raise HTTPError(http.NOT_FOUND) latest_version_number = get_latest_version_number(file_name_clean, node) + 1 for idx, version in enumerate(list(reversed(files_versions))): node_file = NodeFile.load(version) number = len(files_versions) - idx unique, total = get_basic_counters('download:{}:{}:{}'.format( node._primary_key, file_name_clean, number, )) download_url = node_file.download_url(node) api_url = node_file.api_url(node) versions.append({ 'file_name': file_name, 'download_url': download_url, 'version_number': number, 'display_number': number if idx > 0 else 'current', 'modified_date': node_file.date_uploaded.strftime('%Y/%m/%d %I:%M %p'), 'downloads': total if total else 0, 'committer_name': privacy_info_handle( node_file.uploader.fullname, anonymous, name=True ), 'committer_url': privacy_info_handle(node_file.uploader.url, anonymous), }) if number == latest_version_number: latest_download_url = download_url return { 'node_title': node.title, 'file_name': file_name, 'versions': versions, 'registered': node.is_registration, 'urls': { 'api': api_url, 'files': files_page_url, 'latest': { 'download': latest_download_url, }, } }
def _get_summary(node, auth, rescale_ratio, primary=True, link_id=None, show_path=False): # TODO(sloria): Refactor this or remove (lots of duplication with _view_project) summary = { "id": link_id if link_id else node._id, "primary": primary, "is_registration": node.is_registration, "is_fork": node.is_fork, "is_pending_registration": node.is_pending_registration, "is_retracted": node.is_retracted, "is_pending_retraction": node.is_pending_retraction, "embargo_end_date": node.embargo_end_date.strftime("%A, %b. %d, %Y") if node.embargo_end_date else False, "is_pending_embargo": node.is_pending_embargo, "archiving": node.archiving, } if node.can_view(auth): summary.update( { "can_view": True, "can_edit": node.can_edit(auth), "primary_id": node._id, "url": node.url, "primary": primary, "api_url": node.api_url, "title": node.title, "category": node.category, "node_type": node.project_or_component, "is_fork": node.is_fork, "is_registration": node.is_registration, "anonymous": has_anonymous_link(node, auth), "registered_date": node.registered_date.strftime("%Y-%m-%d %H:%M UTC") if node.is_registration else None, "forked_date": node.forked_date.strftime("%Y-%m-%d %H:%M UTC") if node.is_fork else None, "nlogs": None, "ua_count": None, "ua": None, "non_ua": None, "addons_enabled": node.get_addon_names(), "is_public": node.is_public, "parent_title": node.parent_node.title if node.parent_node else None, "parent_is_public": node.parent_node.is_public if node.parent_node else False, "show_path": show_path, } ) if rescale_ratio: ua_count, ua, non_ua = _get_user_activity(node, auth, rescale_ratio) summary.update({"nlogs": len(node.logs), "ua_count": ua_count, "ua": ua, "non_ua": non_ua}) else: summary["can_view"] = False # TODO: Make output format consistent with _view_project return {"summary": summary}
def list_comments(auth, node, **kwargs): anonymous = has_anonymous_link(node, auth) guid = request.args.get('target') target = resolve_target(node, guid) serialized_comments = serialize_comments(target, auth, anonymous) n_unread = 0 if node.is_contributor(auth.user): if auth.user.comments_viewed_timestamp is None: auth.user.comments_viewed_timestamp = {} auth.user.save() n_unread = n_unread_comments(target, auth.user) return { 'comments': serialized_comments, 'nUnread': n_unread }
def osf_storage_get_revisions(payload, node_addon, **kwargs): node = node_addon.owner path = payload.get('path') is_anon = has_anonymous_link(node, Auth(private_key=payload.get('view_only'))) if not path: raise HTTPError(httplib.BAD_REQUEST) record = model.OsfStorageFileNode.get(path.strip('/'), node_addon) # Return revisions in descending order return { 'revisions': [ utils.serialize_revision(node, record, version, index=len(record.versions) - idx - 1, anon=is_anon) for idx, version in enumerate(reversed(record.versions)) ] }
def get_node_contributors_abbrev(auth, **kwargs): node = kwargs['node'] or kwargs['project'] anonymous = has_anonymous_link(node, auth) max_count = kwargs.get('max_count', 3) if 'user_ids' in kwargs: users = [ User.load(user_id) for user_id in kwargs['user_ids'] if user_id in node.visible_contributor_ids ] else: users = node.visible_contributors if anonymous or not node.can_view(auth): raise HTTPError(http.FORBIDDEN) contributors = [] n_contributors = len(users) others_count = '' for index, user in enumerate(users[:max_count]): if index == max_count - 1 and len(users) > max_count: separator = ' &' others_count = str(n_contributors - 3) elif index == len(users) - 1: separator = '' elif index == len(users) - 2: separator = ' &' else: separator = ',' contributors.append({ 'user_id': user._primary_key, 'separator': separator, }) return { 'contributors': contributors, 'others_count': others_count, }
def _get_logs(node, count, auth, link=None, page=0): """ :param Node node: :param int count: :param auth: :return list: List of serialized logs, boolean: if there are more logs """ logs_set = node.get_aggregate_logs_queryset(auth) total = len(logs_set) start = page * count stop = start + count logs = [ serialize_log(log, auth=auth, anonymous=has_anonymous_link(node, auth)) for log in logs_set[start:stop] ] pages = math.ceil(total / float(count)) return logs, total, pages
def get_node_contributors_abbrev(auth, node, **kwargs): anonymous = has_anonymous_link(node, auth) formatter = 'surname' max_count = kwargs.get('max_count', 3) if 'user_ids' in kwargs: users = [ User.load(user_id) for user_id in kwargs['user_ids'] if user_id in node.visible_contributor_ids ] else: users = node.visible_contributors if anonymous or not node.can_view(auth): raise HTTPError(http.FORBIDDEN) contributors = [] n_contributors = len(users) others_count = '' for index, user in enumerate(users[:max_count]): if index == max_count - 1 and len(users) > max_count: separator = ' &' others_count = str(n_contributors - 3) elif index == len(users) - 1: separator = '' elif index == len(users) - 2: separator = ' &' else: separator = ',' contributor = user.get_summary(formatter) contributor['user_id'] = user._primary_key contributor['separator'] = separator contributors.append(contributor) return { 'contributors': contributors, 'others_count': others_count, }
def osfstorage_get_revisions(file_node, node_addon, payload, **kwargs): from osf.models import PageCounter, FileVersion # TODO Fix me onces django works is_anon = has_anonymous_link(node_addon.owner, Auth(private_key=request.args.get('view_only'))) counter_prefix = 'download:{}:{}:'.format(file_node.node._id, file_node._id) version_count = file_node.versions.count() # Don't worry. The only % at the end of the LIKE clause, the index is still used counts = dict(PageCounter.objects.filter(_id__startswith=counter_prefix).values_list('_id', 'total')) qs = FileVersion.includable_objects.filter(basefilenode__id=file_node.id).include('creator__guids').order_by('-created') for i, version in enumerate(qs): version._download_count = counts.get('{}{}'.format(counter_prefix, version_count - i - 1), 0) # Return revisions in descending order return { 'revisions': [ utils.serialize_revision(node_addon.owner, file_node, version, index=version_count - idx - 1, anon=is_anon) for idx, version in enumerate(qs) ] }
def node_register_template_page(auth, node, metaschema_id, **kwargs): if node.is_registration and bool(node.registered_schema): try: meta_schema = MetaSchema.find_one( Q('_id', 'eq', metaschema_id) ) except NoResultsFound: # backwards compatability for old urls, lookup by name try: meta_schema = MetaSchema.find( Q('name', 'eq', _id_to_name(metaschema_id)) ).sort('-schema_version')[0] except IndexError: raise HTTPError(http.NOT_FOUND, data={ 'message_short': 'Invalid schema name', 'message_long': 'No registration schema with that name could be found.' }) if meta_schema not in node.registered_schema: raise HTTPError(http.BAD_REQUEST, data={ 'message_short': 'Invalid schema', 'message_long': 'This registration has no registration supplment with that name.' }) ret = _view_project(node, auth, primary=True) my_meta = serialize_meta_schema(meta_schema) if has_anonymous_link(node, auth): for indx, schema_page in enumerate(my_meta['schema']['pages']): for idx, schema_question in enumerate(schema_page['questions']): if schema_question['title'] in settings.ANONYMIZED_TITLES: del my_meta['schema']['pages'][indx]['questions'][idx] ret['node']['registered_schema'] = serialize_meta_schema(meta_schema) return ret else: status.push_status_message( 'You have been redirected to the project\'s registrations page. From here you can initiate a new Draft Registration to complete the registration process', trust=False ) return redirect(node.web_url_for('node_registrations', view=kwargs.get('template')))
def project_wiki_page(auth, wname, **kwargs): node = kwargs['node'] or kwargs['project'] anonymous = has_anonymous_link(node, auth) wiki_name = (wname or '').strip() wiki_page = node.get_wiki_page(name=wiki_name) status_code = 200 version = 'NA' is_current = False content = '' if wiki_page: version = wiki_page.version is_current = wiki_page.is_current content = wiki_page.html(node) elif not wiki_page and wiki_name.lower() != 'home': status_code = 404 ret = { 'wiki_id': wiki_page._primary_key if wiki_page else None, 'wiki_name': wiki_page.page_name if wiki_page else wiki_name, 'wiki_content': content, 'page': wiki_page, 'version': version, 'versions': _get_wiki_versions(node, wiki_name, anonymous=anonymous), 'is_current': is_current, 'is_edit': False, 'pages_current': _get_wiki_pages_current(node), 'toc': _serialize_wiki_toc(node, auth=auth), 'category': node.category, 'urls': { 'api': _get_wiki_api_urls(node, wiki_name), 'web': _get_wiki_web_urls(node, wiki_name), }, } ret.update(_view_project(node, auth, primary=True)) return ret, status_code
def project_wiki_compare(auth, wname, wver, **kwargs): node = kwargs['node'] or kwargs['project'] anonymous = has_anonymous_link(node, auth) wiki_name = wname.strip() wiki_page = node.get_wiki_page(wiki_name) toc = _serialize_wiki_toc(node, auth=auth) if not wiki_page: raise HTTPError(http.NOT_FOUND) comparison_page = node.get_wiki_page(wiki_name, wver) if comparison_page: current = wiki_page.content comparison = comparison_page.content sm = difflib.SequenceMatcher(None, comparison, current) content = show_diff(sm) content = content.replace('\n', '<br />') ret = { 'wiki_id': wiki_page._primary_key, 'wiki_name': wiki_page.page_name, 'wiki_content': content, 'versions': _get_wiki_versions(node, wiki_name, anonymous), 'is_current': True, 'is_edit': False, 'version': wiki_page.version, 'compare_version': wver, 'pages_current': _get_wiki_pages_current(node), 'toc': toc, 'category': node.category, 'urls': { 'api': _get_wiki_api_urls(node, wiki_name), 'web': _get_wiki_web_urls(node, wiki_name, wver), }, } ret.update(_view_project(node, auth, primary=True)) return ret raise HTTPError(http.NOT_FOUND)
def _view_project(node, auth, primary=False): """Build a JSON object containing everything needed to render project.view.mako. """ user = auth.user parent = node.parent_node if user: dashboard = find_dashboard(user) dashboard_id = dashboard._id in_dashboard = dashboard.pointing_at(node._primary_key) is not None else: in_dashboard = False dashboard_id = "" view_only_link = auth.private_key or request.args.get("view_only", "").strip("/") anonymous = has_anonymous_link(node, auth) widgets, configs, js, css = _render_addon(node) redirect_url = node.url + "?view_only=None" # Before page load callback; skip if not primary call if primary: for addon in node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind="info", dismissible=False, trust=True) data = { "node": { "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_dashboard, "is_public": node.is_public, "is_archiving": node.archiving, "date_created": iso8601format(node.date_created), "date_modified": iso8601format(node.logs[-1].date) if node.logs else "", "tags": [tag._primary_key for tag in node.tags], "children": bool(node.nodes_active), "is_registration": node.is_registration, "is_pending_registration": node.is_pending_registration, "is_retracted": node.is_retracted, "is_pending_retraction": node.is_pending_retraction, "retracted_justification": getattr(node.retraction, "justification", None), "embargo_end_date": node.embargo_end_date.strftime("%A, %b. %d, %Y") if node.embargo_end_date else False, "is_pending_embargo": node.is_pending_embargo, "registered_from_url": node.registered_from.url if node.is_registration else "", "registered_date": iso8601format(node.registered_date) if node.is_registration else "", "root_id": node.root._id, "registered_meta": node.registered_meta, "registered_schemas": serialize_meta_schemas(node.registered_schema), "registration_count": len(node.node__registrations), "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": len(node.forks), "templated_count": len(node.templated_list), "watched_count": len(node.watchconfig__watched), "private_links": [x.to_json() for x in node.private_links_active], "link": view_only_link, "anonymous": anonymous, "points": len(node.get_points(deleted=False, folders=False)), "piwik_site_id": node.piwik_site_id, "comment_level": node.comment_level, "has_comments": bool(getattr(node, "commented", [])), "has_children": bool(getattr(node, "commented", False)), "identifiers": {"doi": node.get_identifier_value("doi"), "ark": node.get_identifier_value("ark")}, "has_draft_registrations": bool(node.draft_registrations_active), }, "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": node.is_contributor(user), "is_admin": node.has_permission(user, ADMIN), "is_admin_parent": parent.is_admin_parent(user) if parent else False, "can_edit": (node.can_edit(auth) and not node.is_registration), "has_read_permissions": node.has_permission(user, READ), "permissions": node.get_permissions(user) if user else [], "is_watching": user.is_watching(node) if user else False, "piwik_token": user.piwik_token if user else "", "id": user._id if user else None, "username": user.username if user else None, "fullname": user.fullname if user else "", "can_comment": node.can_comment(auth), "show_wiki_widget": _should_show_wiki_widget(node, user), "dashboard_id": dashboard_id, }, "badges": _get_badge(user), # TODO: Namespace with nested dicts "addons_enabled": node.get_addon_names(), "addons": configs, "addon_widgets": widgets, "addon_widget_js": js, "addon_widget_css": css, "node_categories": Node.CATEGORY_MAP, } return data
def _view_project(node, auth, primary=False): """Build a JSON object containing everything needed to render project.view.mako. """ user = auth.user parent = node.parent_node if user: dashboard = find_dashboard(user) dashboard_id = dashboard._id in_dashboard = dashboard.pointing_at(node._primary_key) is not None else: in_dashboard = False dashboard_id = '' view_only_link = auth.private_key or request.args.get('view_only', '').strip('/') anonymous = has_anonymous_link(node, auth) widgets, configs, js, css = _render_addon(node) redirect_url = node.url + '?view_only=None' # Before page load callback; skip if not primary call if primary: for addon in node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind='info', dismissible=False, trust=True) data = { 'node': { '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 '', '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_dashboard, 'is_public': node.is_public, 'is_archiving': node.archiving, 'date_created': iso8601format(node.date_created), 'date_modified': iso8601format(node.logs[-1].date) if node.logs else '', 'tags': [tag._primary_key for tag in node.tags], 'children': bool(node.nodes), 'is_registration': node.is_registration, 'is_retracted': node.is_retracted, 'pending_retraction': node.pending_retraction, 'retracted_justification': getattr(node.retraction, 'justification', None), 'embargo_end_date': node.embargo_end_date.strftime("%A, %b. %d, %Y") if node.embargo_end_date else False, 'pending_embargo': node.pending_embargo, 'registered_from_url': node.registered_from.url if node.is_registration else '', 'registered_date': iso8601format(node.registered_date) if node.is_registration else '', 'root_id': node.root._id, 'registered_meta': [{ 'name_no_ext': from_mongo(meta), 'name_clean': clean_template_name(meta), } for meta in node.registered_meta or []], 'registration_count': len(node.node__registrations), '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': len(node.forks), 'templated_count': len(node.templated_list), 'watched_count': len(node.watchconfig__watched), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'anonymous': anonymous, 'points': len(node.get_points(deleted=False, folders=False)), 'piwik_site_id': node.piwik_site_id, 'comment_level': node.comment_level, 'has_comments': bool(getattr(node, 'commented', [])), 'has_children': bool(getattr(node, 'commented', False)), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, }, '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': node.is_contributor(user), 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': (node.can_edit(auth) and not node.is_registration), 'has_read_permissions': node.has_permission(user, 'read'), 'permissions': node.get_permissions(user) if user else [], 'is_watching': user.is_watching(node) if user else False, 'piwik_token': user.piwik_token if user else '', 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, user), 'dashboard_id': dashboard_id, }, 'badges': _get_badge(user), # TODO: Namespace with nested dicts 'addons_enabled': node.get_addon_names(), 'addons': configs, 'addon_widgets': widgets, 'addon_widget_js': js, 'addon_widget_css': css, 'node_categories': Node.CATEGORY_MAP, } return data
def _view_project(node, auth, primary=False): """Build a JSON object containing everything needed to render project.view.mako. """ user = auth.user parent = node.parent_node view_only_link = auth.private_key or request.args.get('view_only', '').strip('/') anonymous = has_anonymous_link(node, auth) widgets, configs, js, css = _render_addon(node) redirect_url = node.url + '?view_only=None' # Before page load callback; skip if not primary call if primary: for addon in node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, dismissible=False) data = { 'node': { 'id': node._primary_key, 'title': node.title, 'category': node.category_display, 'node_type': node.project_or_component, 'description': node.description or '', 'url': node.url, 'api_url': node.api_url, 'absolute_url': node.absolute_url, 'redirect_url': redirect_url, 'display_absolute_url': node.display_absolute_url, 'citations': { 'apa': node.citation_apa, 'mla': node.citation_mla, 'chicago': node.citation_chicago, } if not anonymous else '', 'is_public': node.is_public, 'date_created': iso8601format(node.date_created), 'date_modified': iso8601format(node.logs[-1].date) if node.logs else '', 'tags': [tag._primary_key for tag in node.tags], 'children': bool(node.nodes), 'is_registration': node.is_registration, 'registered_from_url': node.registered_from.url if node.is_registration else '', 'registered_date': iso8601format(node.registered_date) if node.is_registration else '', 'registered_meta': [ { 'name_no_ext': from_mongo(meta), 'name_clean': clean_template_name(meta), } for meta in node.registered_meta or [] ], 'registration_count': len(node.node__registrations), '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': len(node.node__forked.find(Q('is_deleted', 'eq', False))), 'templated_count': len(node.templated_list), 'watched_count': len(node.watchconfig__watched), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'anonymous': anonymous, 'points': len(node.get_points(deleted=False, folders=False)), 'piwik_site_id': node.piwik_site_id, 'comment_level': node.comment_level, 'has_comments': bool(getattr(node, 'commented', [])), 'has_children': bool(getattr(node, 'commented', False)), }, 'parent_node': { 'id': parent._primary_key if parent else '', 'title': parent.title 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 '', 'is_public': parent.is_public if parent else '', 'is_contributor': parent.is_contributor(user) if parent else '', 'can_view': (auth.private_key in parent.private_link_keys_active) if parent else False }, 'user': { 'is_contributor': node.is_contributor(user), 'can_edit': (node.can_edit(auth) and not node.is_registration), 'permissions': node.get_permissions(user) if user else [], 'is_watching': user.is_watching(node) if user else False, 'piwik_token': user.piwik_token if user else '', 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, user), }, 'badges': _get_badge(user), # TODO: Namespace with nested dicts 'addons_enabled': node.get_addon_names(), 'addons': configs, 'addon_widgets': widgets, 'addon_widget_js': js, 'addon_widget_css': css, } return data
def _view_project(node, auth, primary=False): """Build a JSON object containing everything needed to render project.view.mako. """ user = auth.user 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.pointing_at(node._primary_key) is not None 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) widgets, configs, js, css = _render_addon(node) 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 node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind='info', dismissible=False, trust=True) 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.date_created), 'date_modified': iso8601format(node.logs[-1].date) if node.logs else '', 'tags': [tag._primary_key for tag in node.tags], 'children': bool(node.nodes_active), 'is_registration': node.is_registration, 'is_pending_registration': node.is_pending_registration, 'is_retracted': node.is_retracted, 'is_pending_retraction': node.is_pending_retraction, 'retracted_justification': getattr(node.retraction, 'justification', None), 'embargo_end_date': node.embargo_end_date.strftime('%A, %b. %d, %Y') if node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo, 'is_embargoed': node.is_embargoed, 'is_pending_embargo_termination': node.is_embargoed and ( node.embargo_termination_approval and node.embargo_termination_approval.is_pending_approval ), 'registered_from_url': node.registered_from.url if node.is_registration else '', 'registered_date': iso8601format(node.registered_date) if node.is_registration else '', 'root_id': node.root._id if node.root else None, 'registered_meta': node.registered_meta, 'registered_schemas': serialize_meta_schemas(node.registered_schema), 'registration_count': node.registrations_all.count(), '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.count(), 'templated_count': node.templated_list.count(), 'watched_count': node.watches.count(), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'anonymous': anonymous, 'points': len(node.get_points(deleted=False, folders=False)), 'comment_level': node.comment_level, 'has_comments': bool(Comment.find(Q('node', 'eq', node))), 'has_children': bool(Comment.find(Q('node', 'eq', node))), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, 'institutions': get_affiliated_institutions(node) if node else [], 'alternative_citations': [citation.to_json() for citation in node.alternative_citations], 'has_draft_registrations': node.has_active_draft_registrations, 'contributors': [contributor._id for contributor in node.contributors], 'is_preprint': node.is_preprint, 'is_preprint_orphan': node.is_preprint_orphan, 'preprint_file_id': node.preprint_file._id if node.preprint_file else None }, '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': node.is_contributor(user), 'is_admin': node.has_permission(user, ADMIN), 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': (node.can_edit(auth) and not node.is_registration), 'has_read_permissions': node.has_permission(user, READ), 'permissions': node.get_permissions(user) if user else [], 'is_watching': user.is_watching(node) if user else False, 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, user), 'dashboard_id': bookmark_collection_id, 'institutions': get_affiliated_institutions(user) if user else [], }, 'badges': _get_badge(user), # TODO: Namespace with nested dicts 'addons_enabled': node.get_addon_names(), '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() ] } return data
def _get_summary(node, auth, rescale_ratio, primary=True, link_id=None, show_path=False): # TODO(sloria): Refactor this or remove (lots of duplication with _view_project) summary = { 'id': link_id if link_id else node._id, 'primary': primary, 'is_registration': node.is_registration, 'is_fork': node.is_fork, 'is_retracted': node.is_retracted, 'pending_retraction': node.pending_retraction, 'embargo_end_date': node.embargo_end_date.strftime("%A, %b. %d, %Y") if node.embargo_end_date else False, 'pending_embargo': node.pending_embargo, 'archiving': node.archiving, } if node.can_view(auth): summary.update({ 'can_view': True, 'can_edit': node.can_edit(auth), 'primary_id': node._id, 'url': node.url, 'primary': primary, 'api_url': node.api_url, 'title': node.title, 'category': node.category, 'node_type': node.project_or_component, 'is_fork': node.is_fork, 'is_registration': node.is_registration, 'anonymous': has_anonymous_link(node, auth), 'registered_date': node.registered_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_registration else None, 'forked_date': node.forked_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_fork else None, 'nlogs': None, 'ua_count': None, 'ua': None, 'non_ua': None, 'addons_enabled': node.get_addon_names(), 'is_public': node.is_public, 'parent_title': node.parent_node.title if node.parent_node else None, 'parent_is_public': node.parent_node.is_public if node.parent_node else False, 'show_path': show_path }) if rescale_ratio: ua_count, ua, non_ua = _get_user_activity(node, auth, rescale_ratio) summary.update({ 'nlogs': len(node.logs), 'ua_count': ua_count, 'ua': ua, 'non_ua': non_ua, }) else: summary['can_view'] = False # TODO: Make output format consistent with _view_project return { 'summary': summary, }
def serialize_node_summary(node, auth, primary=True, show_path=False): is_registration = node.is_registration summary = { 'id': node._id, 'primary': primary, 'is_registration': node.is_registration, 'is_fork': node.is_fork, '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, 'embargo_end_date': node.embargo_end_date.strftime('%A, %b. %d, %Y') if is_registration and node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo if is_registration else False, 'is_embargoed': node.is_embargoed if is_registration else False, 'archiving': node.archiving if is_registration else False, } parent_node = node.parent_node user = auth.user if node.can_view(auth): # Re-query node with contributor guids included to prevent N contributor queries node = AbstractNode.objects.filter(pk=node.pk).include('contributor__user__guids').get() contributor_data = serialize_contributors_for_summary(node) summary.update({ 'can_view': True, 'can_edit': node.can_edit(auth), 'primary_id': node._id, 'url': node.url, 'primary': primary, 'api_url': node.api_url, 'title': node.title, 'category': node.category, 'isPreprint': bool(node.preprint_file_id), 'childExists': Node.objects.get_children(node, active=True).exists(), 'is_admin': node.has_permission(user, permissions.ADMIN), 'is_contributor': node.is_contributor(user), 'logged_in': auth.logged_in, 'node_type': node.project_or_component, 'is_fork': node.is_fork, 'is_registration': is_registration, 'anonymous': has_anonymous_link(node, auth), 'registered_date': node.registered_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_registration else None, 'forked_date': node.forked_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_fork else None, 'ua_count': None, 'ua': None, 'non_ua': None, 'is_public': node.is_public, 'parent_title': parent_node.title if parent_node else None, 'parent_is_public': parent_node.is_public if parent_node else False, 'show_path': show_path, 'contributors': contributor_data['contributors'], 'others_count': contributor_data['others_count'], 'description': node.description if len(node.description) <= 150 else node.description[0:150] + '...', }) else: summary['can_view'] = False return summary
def project_wiki_view(auth, wname, path=None, **kwargs): node = kwargs['node'] or kwargs['project'] anonymous = has_anonymous_link(node, auth) wiki_name = (wname or '').strip() wiki_key = to_mongo_key(wiki_name) wiki_page = WikiPage.objects.get_for_node(node, wiki_name) wiki_version = WikiVersion.objects.get_for_node(node, wiki_name) wiki_settings = node.get_addon('wiki') can_edit = (auth.logged_in and not node.is_registration and (node.has_permission(auth.user, WRITE) or wiki_settings.is_publicly_editable)) versions = _get_wiki_versions(node, wiki_name, anonymous=anonymous) # Determine panels used in view panels = {'view', 'edit', 'compare', 'menu'} if request.args and set(request.args).intersection(panels): panels_used = [panel for panel in request.args if panel in panels] num_columns = len( set(panels_used).intersection({'view', 'edit', 'compare'})) if num_columns == 0: panels_used.append('view') num_columns = 1 else: panels_used = ['view', 'menu'] num_columns = 1 try: view = wiki_utils.format_wiki_version( version=request.args.get('view'), num_versions=len(versions), allow_preview=True, ) compare = wiki_utils.format_wiki_version( version=request.args.get('compare'), num_versions=len(versions), allow_preview=False, ) except InvalidVersionError: raise WIKI_INVALID_VERSION_ERROR # ensure home is always lower case since it cannot be renamed if wiki_name.lower() == 'home': wiki_name = 'home' if wiki_version: version = wiki_version.identifier is_current = wiki_version.is_current content = wiki_version.html(node) rendered_before_update = wiki_version.rendered_before_update else: version = 'NA' is_current = False content = '' rendered_before_update = False if can_edit: if wiki_key not in node.wiki_private_uuids: wiki_utils.generate_private_uuid(node, wiki_name) sharejs_uuid = wiki_utils.get_sharejs_uuid(node, wiki_name) else: if not wiki_page and wiki_key != 'home': raise WIKI_PAGE_NOT_FOUND_ERROR if 'edit' in request.args: if wiki_settings.is_publicly_editable: raise HTTPError(http_status.HTTP_401_UNAUTHORIZED) if node.can_view(auth): return redirect( node.web_url_for('project_wiki_view', wname=wname, _guid=True)) raise HTTPError(http_status.HTTP_403_FORBIDDEN) sharejs_uuid = None # Opens 'edit' panel when home wiki is empty if not content and can_edit and wiki_name == 'home': panels_used.append('edit') # Default versions for view and compare version_settings = { 'view': view or ('preview' if 'edit' in panels_used else 'current'), 'compare': compare or 'previous', } ret = { 'wiki_id': wiki_page._primary_key if wiki_page else None, 'wiki_name': wiki_page.page_name if wiki_page else wiki_name, 'wiki_content': content, 'rendered_before_update': rendered_before_update, 'page': wiki_page, 'version': version, 'versions': versions, 'sharejs_uuid': sharejs_uuid or '', 'sharejs_url': settings.SHAREJS_URL, 'is_current': is_current, 'version_settings': version_settings, 'pages_current': _get_wiki_pages_latest(node), 'category': node.category, 'panels_used': panels_used, 'num_columns': num_columns, 'urls': { 'api': _get_wiki_api_urls( node, wiki_name, { 'content': node.api_url_for('wiki_page_content', wname=wiki_name), 'draft': node.api_url_for('wiki_page_draft', wname=wiki_name), }), 'web': _get_wiki_web_urls(node, wiki_name), 'profile_image': get_profile_image_url(auth.user, 25), }, } ret.update(_view_project(node, auth, primary=True)) ret['user']['can_edit_wiki_body'] = can_edit return ret
def project_wiki_view(auth, wname, path=None, **kwargs): node = kwargs["node"] or kwargs["project"] anonymous = has_anonymous_link(node, auth) wiki_name = (wname or "").strip() wiki_key = to_mongo_key(wiki_name) wiki_page = node.get_wiki_page(wiki_name) wiki_settings = node.get_addon("wiki") can_edit = ( auth.logged_in and not node.is_registration and (node.has_permission(auth.user, "write") or wiki_settings.is_publicly_editable) ) versions = _get_wiki_versions(node, wiki_name, anonymous=anonymous) # Determine panels used in view panels = {"view", "edit", "compare", "menu"} if request.args and set(request.args).intersection(panels): panels_used = [panel for panel in request.args if panel in panels] num_columns = len(set(panels_used).intersection({"view", "edit", "compare"})) if num_columns == 0: panels_used.append("view") num_columns = 1 else: panels_used = ["view", "menu"] num_columns = 1 try: view = wiki_utils.format_wiki_version( version=request.args.get("view"), num_versions=len(versions), allow_preview=True ) compare = wiki_utils.format_wiki_version( version=request.args.get("compare"), num_versions=len(versions), allow_preview=False ) except InvalidVersionError: raise WIKI_INVALID_VERSION_ERROR # Default versions for view and compare version_settings = { "view": view or ("preview" if "edit" in panels_used else "current"), "compare": compare or "previous", } # ensure home is always lower case since it cannot be renamed if wiki_name.lower() == "home": wiki_name = "home" if wiki_page: version = wiki_page.version is_current = wiki_page.is_current content = wiki_page.html(node) use_python_render = wiki_page.rendered_before_update else: version = "NA" is_current = False content = "" use_python_render = False if can_edit: if wiki_key not in node.wiki_private_uuids: wiki_utils.generate_private_uuid(node, wiki_name) sharejs_uuid = wiki_utils.get_sharejs_uuid(node, wiki_name) else: if wiki_key not in node.wiki_pages_current and wiki_key != "home": raise WIKI_PAGE_NOT_FOUND_ERROR if "edit" in request.args: if wiki_settings.is_publicly_editable: raise HTTPError(http.UNAUTHORIZED) raise HTTPError(http.FORBIDDEN) sharejs_uuid = None ret = { "wiki_id": wiki_page._primary_key if wiki_page else None, "wiki_name": wiki_page.page_name if wiki_page else wiki_name, "wiki_content": content, "use_python_render": use_python_render, "page": wiki_page, "version": version, "versions": versions, "sharejs_uuid": sharejs_uuid or "", "sharejs_url": settings.SHAREJS_URL, "is_current": is_current, "version_settings": version_settings, "pages_current": _get_wiki_pages_current(node), "category": node.category, "panels_used": panels_used, "num_columns": num_columns, "urls": { "api": _get_wiki_api_urls( node, wiki_name, { "content": node.api_url_for("wiki_page_content", wname=wiki_name), "draft": node.api_url_for("wiki_page_draft", wname=wiki_name), }, ), "web": _get_wiki_web_urls(node, wiki_name), "gravatar": get_gravatar(auth.user, 25), }, } ret.update(_view_project(node, auth, primary=True)) ret["user"]["can_edit_wiki_body"] = can_edit 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 = Node.objects.filter(pk=node.pk).include('contributor__user__guids').get() user = auth.user 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) widgets, configs, js, css = _render_addon(node) 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 node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind='info', dismissible=False, trust=True) 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.date_created), 'date_modified': iso8601format(node.logs.latest().date) if node.logs.exists() else '', 'tags': list(node.tags.filter(system=False).values_list('name', flat=True)), 'children': bool(node.nodes_active), 'is_registration': node.is_registration, 'is_pending_registration': node.is_pending_registration, 'is_retracted': node.is_retracted, 'is_pending_retraction': node.is_pending_retraction, 'retracted_justification': getattr(node.retraction, 'justification', None), 'date_retracted': iso8601format(getattr(node.retraction, 'date_retracted', None)), 'embargo_end_date': node.embargo_end_date.strftime('%A, %b. %d, %Y') if node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo, 'is_embargoed': node.is_embargoed, 'is_pending_embargo_termination': node.is_embargoed and ( node.embargo_termination_approval and node.embargo_termination_approval.is_pending_approval ), 'registered_from_url': node.registered_from.url if node.is_registration else '', 'registered_date': iso8601format(node.registered_date) if node.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())), 'registration_count': node.registrations_all.count(), '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.filter(is_deleted=False).count(), 'templated_count': node.templated_list.count(), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'anonymous': anonymous, 'points': len(node.get_points(deleted=False, folders=False)), 'comment_level': node.comment_level, 'has_comments': bool(Comment.find(Q('node', 'eq', node))), 'has_children': bool(Comment.find(Q('node', 'eq', node))), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, 'institutions': get_affiliated_institutions(node) if node else [], 'alternative_citations': [citation.to_json() for citation in node.alternative_citations.all()], 'has_draft_registrations': node.has_active_draft_registrations, 'contributors': list(node.contributors.values_list('guids___id', flat=True)), 'is_preprint': node.is_preprint, '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': node.is_contributor(user), 'is_admin': node.has_permission(user, ADMIN), 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': (node.can_edit(auth) and not node.is_registration), 'has_read_permissions': node.has_permission(user, READ), 'permissions': node.get_permissions(user) if user else [], 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, user), 'dashboard_id': bookmark_collection_id, 'institutions': get_affiliated_institutions(user) if user else [], }, 'badges': _get_badge(user), # TODO: Namespace with nested dicts 'addons_enabled': node.get_addon_names(), '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) 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 github_view_file(auth, **kwargs): node = kwargs['node'] or kwargs['project'] node_settings = kwargs['node_addon'] path = get_path(kwargs) file_name = os.path.split(path)[1] # Get branch / commit branch = request.args.get('branch') sha = request.args.get('sha', branch) ref = sha or branch connection = GitHub.from_settings(node_settings.user_settings) # Get current file for delete url current_file = connection.contents(user=node_settings.user, repo=node_settings.repo, path=path, ref=sha or branch) anonymous = has_anonymous_link(node, auth) try: # If GUID has already been created, we won't redirect, and can check # whether the file exists below guid = GithubGuidFile.find_one( Q('node', 'eq', node) & Q('path', 'eq', path)) except ModularOdmException: # If GUID doesn't exist, check whether file exists before creating commits = connection.history( node_settings.user, node_settings.repo, path, ref, ) if not commits: raise HTTPError(http.NOT_FOUND) guid = GithubGuidFile( node=node, path=path, ) guid.save() redirect_url = check_file_guid(guid) if redirect_url: return redirect(redirect_url) # Get default branch if neither SHA nor branch is provided if ref is None: repo = connection.repo(node_settings.user, node_settings.repo) ref = branch = repo.default_branch # Get file history; use SHA or branch if registered, else branch start_sha = ref if node.is_registration else branch commits = connection.history(node_settings.user, node_settings.repo, path, sha=start_sha) # Get current commit shas = [commit['sha'] for commit in commits] if not shas: raise HTTPError(http.NOT_FOUND) current_sha = sha if sha in shas else shas[0] # Get file URL download_url = '/' + guid._id + '/download/' + ref_to_params( branch, current_sha) render_url = os.path.join(node.api_url, 'github', 'file', path, 'render') + '/' + ref_to_params( branch, current_sha) delete_url = None if current_file: delete_url = node.api_url_for('github_delete_file', path=path) + ref_to_params( branch, current_file.sha) for commit in commits: commit['download'] = ('/' + guid._id + '/download/' + ref_to_params(sha=commit['sha'])) commit['view'] = ('/' + guid._id + '/' + ref_to_params(branch, sha=commit['sha'])) if anonymous: commit['name'] = 'A user' commit['email'] = '' # Get or create rendered file cache_file_name = get_cache_file( path, current_sha, ) rendered = get_cache_content(node_settings, cache_file_name) if rendered is None: try: _, data, size = connection.file( node_settings.user, node_settings.repo, path, ref=sha, ) except TooBigError: rendered = 'File too large to download.' if rendered is None: # Skip if too large to be rendered. if github_settings.MAX_RENDER_SIZE is not None and size > github_settings.MAX_RENDER_SIZE: rendered = 'File too large to render; download file to view it.' else: rendered = get_cache_content( node_settings, cache_file_name, start_render=True, remote_path=guid.path, file_content=data, download_url=download_url, ) rv = { 'node': { 'id': node._id, 'title': node.title }, 'file_name': file_name, 'files_page_url': node.web_url_for('collect_file_trees'), 'current_sha': current_sha, 'render_url': render_url, 'rendered': rendered, 'download_url': download_url, 'delete_url': delete_url, 'commits': commits, } rv.update(_view_project(node, auth, primary=True)) return rv
def serialize_node_summary(node, auth, primary=True, show_path=False): is_registration = node.is_registration summary = { 'id': node._id, 'primary': primary, 'is_registration': node.is_registration, 'is_fork': node.is_fork, '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, 'embargo_end_date': node.embargo_end_date.strftime('%A, %b. %d, %Y') if is_registration and node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo if is_registration else False, 'is_embargoed': node.is_embargoed if is_registration else False, 'archiving': node.archiving if is_registration else False, } parent_node = node.parent_node user = auth.user if node.can_view(auth): # Re-query node with contributor guids included to prevent N contributor queries node = AbstractNode.objects.filter( pk=node.pk).include('contributor__user__guids').get() contributor_data = serialize_contributors_for_summary(node) summary.update({ 'can_view': True, 'can_edit': node.can_edit(auth), 'primary_id': node._id, 'url': node.url, 'primary': primary, 'api_url': node.api_url, 'title': node.title, 'category': node.category, 'isPreprint': bool(node.preprint_file_id), 'childExists': Node.objects.get_children(node, active=True).exists(), 'is_admin': node.has_permission(user, permissions.ADMIN), 'is_contributor': node.is_contributor(user), 'logged_in': auth.logged_in, 'node_type': node.project_or_component, 'is_fork': node.is_fork, 'is_registration': is_registration, 'anonymous': has_anonymous_link(node, auth), 'registered_date': node.registered_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_registration else None, 'forked_date': node.forked_date.strftime('%Y-%m-%d %H:%M UTC') if node.is_fork else None, 'ua_count': None, 'ua': None, 'non_ua': None, 'is_public': node.is_public, 'parent_title': parent_node.title if parent_node else None, 'parent_is_public': parent_node.is_public if parent_node else False, 'show_path': show_path, 'contributors': contributor_data['contributors'], 'others_count': contributor_data['others_count'], 'description': node.description if len(node.description) <= 150 else node.description[0:150] + '...', }) else: summary['can_view'] = False return summary
def _view_project(node, auth, primary=False): """Build a JSON object containing everything needed to render project.view.mako. """ user = auth.user parent = node.parent_node if user: bookmark_collection = find_bookmark_collection(user) bookmark_collection_id = bookmark_collection._id in_bookmark_collection = bookmark_collection.pointing_at(node._primary_key) is not None 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) widgets, configs, js, css = _render_addon(node) 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', '') # Before page load callback; skip if not primary call if primary: for addon in node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, kind='info', dismissible=False, trust=True) 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.date_created), 'date_modified': iso8601format(node.logs[-1].date) if node.logs else '', 'tags': [tag._primary_key for tag in node.tags], 'children': bool(node.nodes_active), 'is_registration': node.is_registration, 'is_pending_registration': node.is_pending_registration, 'is_retracted': node.is_retracted, 'is_pending_retraction': node.is_pending_retraction, 'retracted_justification': getattr(node.retraction, 'justification', None), 'embargo_end_date': node.embargo_end_date.strftime("%A, %b. %d, %Y") if node.embargo_end_date else False, 'is_pending_embargo': node.is_pending_embargo, 'is_embargoed': node.is_embargoed, 'is_pending_embargo_termination': node.is_embargoed and ( node.embargo_termination_approval and node.embargo_termination_approval.is_pending_approval ), 'registered_from_url': node.registered_from.url if node.is_registration else '', 'registered_date': iso8601format(node.registered_date) if node.is_registration else '', 'root_id': node.root._id if node.root else None, 'registered_meta': node.registered_meta, 'registered_schemas': serialize_meta_schemas(node.registered_schema), 'registration_count': node.registrations_all.count(), '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.count(), 'templated_count': node.templated_list.count(), 'watched_count': node.watches.count(), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'anonymous': anonymous, 'points': len(node.get_points(deleted=False, folders=False)), 'piwik_site_id': node.piwik_site_id, 'comment_level': node.comment_level, 'has_comments': bool(Comment.find(Q('node', 'eq', node))), 'has_children': bool(Comment.find(Q('node', 'eq', node))), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, 'institution': { 'name': node.primary_institution.name if node.primary_institution else None, 'logo_path': node.primary_institution.logo_path if node.primary_institution else None, 'id': node.primary_institution._id if node.primary_institution else None }, 'alternative_citations': [citation.to_json() for citation in node.alternative_citations], 'has_draft_registrations': node.has_active_draft_registrations, 'contributors': [contributor._id for contributor in node.contributors] }, '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': node.is_contributor(user), 'is_admin': node.has_permission(user, ADMIN), 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': (node.can_edit(auth) and not node.is_registration), 'has_read_permissions': node.has_permission(user, READ), 'permissions': node.get_permissions(user) if user else [], 'is_watching': user.is_watching(node) if user else False, 'piwik_token': user.piwik_token if user else '', 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, user), 'dashboard_id': bookmark_collection_id, 'institutions': get_affiliated_institutions(user) if user else [], }, 'badges': _get_badge(user), # TODO: Namespace with nested dicts 'addons_enabled': node.get_addon_names(), 'addons': configs, 'addon_widgets': widgets, 'addon_widget_js': js, 'addon_widget_css': css, 'node_categories': Node.CATEGORY_MAP } return data
def _view_project(node, auth, primary=False): """Build a JSON object containing everything needed to render project.view.mako. """ user = auth.user parent = node.parent_node if user: dashboard = find_dashboard(user) dashboard_id = dashboard._id in_dashboard = dashboard.pointing_at(node._primary_key) is not None else: in_dashboard = False dashboard_id = '' view_only_link = auth.private_key or request.args.get('view_only', '').strip('/') anonymous = has_anonymous_link(node, auth) widgets, configs, js, css = _render_addon(node) redirect_url = node.url + '?view_only=None' # Before page load callback; skip if not primary call if primary: for addon in node.get_addons(): messages = addon.before_page_load(node, user) or [] for message in messages: status.push_status_message(message, dismissible=False) data = { 'node': { '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 '', '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_dashboard, 'is_public': node.is_public, 'date_created': iso8601format(node.date_created), 'date_modified': iso8601format(node.logs[-1].date) if node.logs else '', 'tags': [tag._primary_key for tag in node.tags], 'children': bool(node.nodes), 'is_registration': node.is_registration, 'registered_from_url': node.registered_from.url if node.is_registration else '', 'registered_date': iso8601format(node.registered_date) if node.is_registration else '', 'registered_meta': [ { 'name_no_ext': from_mongo(meta), 'name_clean': clean_template_name(meta), } for meta in node.registered_meta or [] ], 'registration_count': len(node.node__registrations), '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': len(node.forks), 'templated_count': len(node.templated_list), 'watched_count': len(node.watchconfig__watched), 'private_links': [x.to_json() for x in node.private_links_active], 'link': view_only_link, 'anonymous': anonymous, 'points': len(node.get_points(deleted=False, folders=False)), 'piwik_site_id': node.piwik_site_id, 'comment_level': node.comment_level, 'has_comments': bool(getattr(node, 'commented', [])), 'has_children': bool(getattr(node, 'commented', False)), 'identifiers': { 'doi': node.get_identifier_value('doi'), 'ark': node.get_identifier_value('ark'), }, }, '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': node.is_contributor(user), 'is_admin_parent': parent.is_admin_parent(user) if parent else False, 'can_edit': (node.can_edit(auth) and not node.is_registration), 'has_read_permissions': node.has_permission(user, 'read'), 'permissions': node.get_permissions(user) if user else [], 'is_watching': user.is_watching(node) if user else False, 'piwik_token': user.piwik_token if user else '', 'id': user._id if user else None, 'username': user.username if user else None, 'fullname': user.fullname if user else '', 'can_comment': node.can_comment(auth), 'show_wiki_widget': _should_show_wiki_widget(node, user), 'dashboard_id': dashboard_id, }, 'badges': _get_badge(user), # TODO: Namespace with nested dicts 'addons_enabled': node.get_addon_names(), 'addons': configs, 'addon_widgets': widgets, 'addon_widget_js': js, 'addon_widget_css': css, 'node_categories': Node.CATEGORY_MAP, } 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
def figshare_view_file(*args, **kwargs): auth = kwargs['auth'] node = kwargs['node'] or kwargs['project'] node_settings = kwargs['node_addon'] article_id = kwargs.get('aid') or None file_id = kwargs.get('fid') or None anonymous = has_anonymous_link(node, auth) if not article_id or not file_id: raise HTTPError(http.NOT_FOUND) connect = Figshare.from_settings(node_settings.user_settings) if node_settings.figshare_type == 'project': item = connect.project(node_settings, node_settings.figshare_id) else: item = connect.article(node_settings, node_settings.figshare_id) if article_id not in str(item): raise HTTPError(http.NOT_FOUND) article = connect.article(node_settings, article_id) found = False for f in article['items'][0]['files']: if f['id'] == int(file_id): found = f break if not found: raise HTTPError(http.NOT_FOUND) try: # If GUID has already been created, we won't redirect, and can check # whether the file exists below guid = FigShareGuidFile.find_one( Q('node', 'eq', node) & Q('article_id', 'eq', article_id) & Q('file_id', 'eq', file_id) ) except: guid = FigShareGuidFile(node=node, article_id=article_id, file_id=file_id) guid.save() redirect_url = check_file_guid(guid) if redirect_url: return redirect(redirect_url) private = not(article['items'][0]['status'] == 'Public') figshare_url = 'http://figshare.com/' if private: figshare_url += 'preview/_preview/{0}'.format(article['items'][0]['article_id']) else: figshare_url += 'articles/{0}/{1}'.format(article['items'][0]['title'].replace(' ', '_'), article['items'][0]['article_id']) version_url = "http://figshare.com/articles/{filename}/{file_id}".format( filename=article['items'][0]['title'], file_id=article['items'][0]['article_id']) download_url = node.api_url + 'figshare/download/article/{aid}/file/{fid}'.format(aid=article_id, fid=file_id) render_url = node.api_url + \ 'figshare/render/article/{aid}/file/{fid}'.format(aid=article_id, fid=file_id) delete_url = node.api_url + 'figshare/article/{aid}/file/{fid}/'.format(aid=article_id, fid=file_id) filename = found['name'] cache_file_name = get_cache_file( article_id, file_id ) rendered = get_cache_content(node_settings, cache_file_name) if private: rendered = messages.FIGSHARE_VIEW_FILE_PRIVATE.format(url='http://figshare.com/') elif rendered is None: filename, size, filedata = connect.get_file(node_settings, found) if figshare_settings.MAX_RENDER_SIZE is not None and size > figshare_settings.MAX_RENDER_SIZE: rendered = messages.FIGSHARE_VIEW_FILE_OVERSIZED.format( url=found.get('download_url')) else: rendered = get_cache_content( node_settings, cache_file_name, start_render=True, remote_path=filename, file_content=filedata, download_url=download_url, ) categories = connect.categories()['items'] # TODO Cache this categories = ''.join( ["<option value='{val}'>{label}</option>".format(val=i['id'], label=i['name']) for i in categories]) rv = { 'node': { 'id': node._id, 'title': node.title }, 'file_name': filename, 'rendered': rendered, 'file_status': article['items'][0]['status'], 'file_version': article['items'][0]['version'], 'doi': 'http://dx.doi.org/10.6084/m9.figshare.{0}'.format(article['items'][0]['article_id']), 'parent_type': 'fileset' if article['items'][0]['defined_type'] == 'fileset' else 'singlefile', 'parent_id': article['items'][0]['article_id'], 'figshare_categories': categories, 'figshare_title': article['items'][0]['title'], 'figshare_desc': article['items'][0]['description'], 'urls': { 'render': render_url, 'download': found.get('download_url'), 'version': version_url, 'figshare': privacy_info_handle(figshare_url, anonymous), 'delete': delete_url, 'files': node.web_url_for('collect_file_trees') } } rv.update(_view_project(node, auth, primary=True)) return rv
def figshare_view_file(*args, **kwargs): auth = kwargs['auth'] node = kwargs['node'] or kwargs['project'] node_settings = kwargs['node_addon'] article_id = kwargs.get('aid') or None file_id = kwargs.get('fid') or None anonymous = has_anonymous_link(node, auth) if not article_id or not file_id: raise HTTPError(http.NOT_FOUND) connect = Figshare.from_settings(node_settings.user_settings) if node_settings.figshare_type == 'project': item = connect.project(node_settings, node_settings.figshare_id) else: item = connect.article(node_settings, node_settings.figshare_id) if article_id not in str(item): raise HTTPError(http.NOT_FOUND) article = connect.article(node_settings, article_id) found = False for f in article['items'][0]['files']: if f['id'] == int(file_id): found = f break if not found: raise HTTPError(http.NOT_FOUND) try: # If GUID has already been created, we won't redirect, and can check # whether the file exists below guid = FigShareGuidFile.find_one( Q('node', 'eq', node) & Q('article_id', 'eq', article_id) & Q('file_id', 'eq', file_id)) except: guid = FigShareGuidFile(node=node, article_id=article_id, file_id=file_id) guid.save() redirect_url = check_file_guid(guid) if redirect_url: return redirect(redirect_url) private = not (article['items'][0]['status'] == 'Public') figshare_url = 'http://figshare.com/' if private: figshare_url += 'preview/_preview/{0}'.format( article['items'][0]['article_id']) else: figshare_url += 'articles/{0}/{1}'.format( article['items'][0]['title'].replace(' ', '_'), article['items'][0]['article_id']) version_url = "http://figshare.com/articles/{filename}/{file_id}".format( filename=article['items'][0]['title'], file_id=article['items'][0]['article_id']) download_url = node.api_url + 'figshare/download/article/{aid}/file/{fid}'.format( aid=article_id, fid=file_id) render_url = node.api_url + \ 'figshare/render/article/{aid}/file/{fid}'.format(aid=article_id, fid=file_id) delete_url = node.api_url + 'figshare/article/{aid}/file/{fid}/'.format( aid=article_id, fid=file_id) filename = found['name'] cache_file_name = get_cache_file(article_id, file_id) rendered = get_cache_content(node_settings, cache_file_name) if private: rendered = messages.FIGSHARE_VIEW_FILE_PRIVATE.format( url='http://figshare.com/') elif rendered is None: filename, size, filedata = connect.get_file(node_settings, found) if figshare_settings.MAX_RENDER_SIZE is not None and size > figshare_settings.MAX_RENDER_SIZE: rendered = messages.FIGSHARE_VIEW_FILE_OVERSIZED.format( url=found.get('download_url')) else: rendered = get_cache_content( node_settings, cache_file_name, start_render=True, remote_path=filename, file_content=filedata, download_url=download_url, ) categories = connect.categories()['items'] # TODO Cache this categories = ''.join([ "<option value='{val}'>{label}</option>".format(val=i['id'], label=i['name']) for i in categories ]) rv = { 'node': { 'id': node._id, 'title': node.title }, 'file_name': filename, 'rendered': rendered, 'file_status': article['items'][0]['status'], 'file_version': article['items'][0]['version'], 'doi': 'http://dx.doi.org/10.6084/m9.figshare.{0}'.format( article['items'][0]['article_id']), 'parent_type': 'fileset' if article['items'][0]['defined_type'] == 'fileset' else 'singlefile', 'parent_id': article['items'][0]['article_id'], 'figshare_categories': categories, 'figshare_title': article['items'][0]['title'], 'figshare_desc': article['items'][0]['description'], 'urls': { 'render': render_url, 'download': found.get('download_url'), 'version': version_url, 'figshare': privacy_info_handle(figshare_url, anonymous), 'delete': delete_url, 'files': node.web_url_for('collect_file_trees') } } rv.update(_view_project(node, auth, primary=True)) return rv
def project_wiki_view(auth, wname, path=None, **kwargs): node = kwargs['node'] or kwargs['project'] anonymous = has_anonymous_link(node, auth) wiki_name = (wname or '').strip() wiki_key = to_mongo_key(wiki_name) wiki_page = node.get_wiki_page(wiki_name) wiki_settings = node.get_addon('wiki') can_edit = ( auth.logged_in and not node.is_registration and ( node.has_permission(auth.user, 'write') or wiki_settings.is_publicly_editable ) ) versions = _get_wiki_versions(node, wiki_name, anonymous=anonymous) # Determine panels used in view panels = {'view', 'edit', 'compare', 'menu'} if request.args and set(request.args).intersection(panels): panels_used = [panel for panel in request.args if panel in panels] num_columns = len(set(panels_used).intersection({'view', 'edit', 'compare'})) if num_columns == 0: panels_used.append('view') num_columns = 1 else: panels_used = ['view', 'menu'] num_columns = 1 try: view = wiki_utils.format_wiki_version( version=request.args.get('view'), num_versions=len(versions), allow_preview=True, ) compare = wiki_utils.format_wiki_version( version=request.args.get('compare'), num_versions=len(versions), allow_preview=False, ) except InvalidVersionError: raise WIKI_INVALID_VERSION_ERROR # Default versions for view and compare version_settings = { 'view': view or ('preview' if 'edit' in panels_used else 'current'), 'compare': compare or 'previous', } # ensure home is always lower case since it cannot be renamed if wiki_name.lower() == 'home': wiki_name = 'home' if wiki_page: version = wiki_page.version is_current = wiki_page.is_current content = wiki_page.html(node) use_python_render = wiki_page.rendered_before_update else: version = 'NA' is_current = False content = '' use_python_render = False if can_edit: if wiki_key not in node.wiki_private_uuids: wiki_utils.generate_private_uuid(node, wiki_name) sharejs_uuid = wiki_utils.get_sharejs_uuid(node, wiki_name) else: if wiki_key not in node.wiki_pages_current and wiki_key != 'home': raise WIKI_PAGE_NOT_FOUND_ERROR if 'edit' in request.args: if wiki_settings.is_publicly_editable: raise HTTPError(http.UNAUTHORIZED) raise HTTPError(http.FORBIDDEN) sharejs_uuid = None # Opens 'edit' panel when home wiki is empty if not content and can_edit and wiki_name == 'home': panels_used.append('edit') ret = { 'wiki_id': wiki_page._primary_key if wiki_page else None, 'wiki_name': wiki_page.page_name if wiki_page else wiki_name, 'wiki_content': content, 'use_python_render': use_python_render, 'page': wiki_page, 'version': version, 'versions': versions, 'sharejs_uuid': sharejs_uuid or '', 'sharejs_url': settings.SHAREJS_URL, 'is_current': is_current, 'version_settings': version_settings, 'pages_current': _get_wiki_pages_current(node), 'category': node.category, 'panels_used': panels_used, 'num_columns': num_columns, 'urls': { 'api': _get_wiki_api_urls(node, wiki_name, { 'content': node.api_url_for('wiki_page_content', wname=wiki_name), 'draft': node.api_url_for('wiki_page_draft', wname=wiki_name), }), 'web': _get_wiki_web_urls(node, wiki_name), 'gravatar': get_gravatar(auth.user, 25), }, } ret.update(_view_project(node, auth, primary=True)) ret['user']['can_edit_wiki_body'] = can_edit return ret
def project_wiki_view(auth, wname, path=None, **kwargs): node = kwargs['node'] or kwargs['project'] anonymous = has_anonymous_link(node, auth) wiki_name = (wname or '').strip() wiki_key = to_mongo_key(wiki_name) wiki_page = node.get_wiki_page(wiki_name) toc = _serialize_wiki_toc(node, auth=auth) can_edit = node.has_permission(auth.user, 'write') and not node.is_registration versions = _get_wiki_versions(node, wiki_name, anonymous=anonymous) # Determine panels used in view panels = {'view', 'edit', 'compare', 'menu'} if request.args and set(request.args).intersection(panels): panels_used = [panel for panel in request.args if panel in panels] num_columns = len(set(panels_used).intersection({'view', 'edit', 'compare'})) if num_columns == 0: panels_used.append('view') num_columns = 1 else: panels_used = ['view', 'menu'] num_columns = 1 try: view = wiki_utils.format_wiki_version( version=request.args.get('view'), num_versions=len(versions), allow_preview=True, ) compare = wiki_utils.format_wiki_version( version=request.args.get('compare'), num_versions=len(versions), allow_preview=False, ) except InvalidVersionError: raise WIKI_INVALID_VERSION_ERROR # Default versions for view and compare version_settings = { 'view': view or ('preview' if 'edit' in panels_used else 'current'), 'compare': compare or 'previous', } # ensure home is always lower case since it cannot be renamed if wiki_name.lower() == 'home': wiki_name = 'home' if wiki_page: version = wiki_page.version is_current = wiki_page.is_current content = wiki_page.html(node) use_python_render = wiki_page.rendered_before_update else: version = 'NA' is_current = False content = '' use_python_render = False if can_edit: if wiki_key not in node.wiki_private_uuids: wiki_utils.generate_private_uuid(node, wiki_name) sharejs_uuid = wiki_utils.get_sharejs_uuid(node, wiki_name) else: if wiki_key not in node.wiki_pages_current and wiki_key != 'home': raise WIKI_PAGE_NOT_FOUND_ERROR if 'edit' in request.args: raise HTTPError(http.FORBIDDEN) sharejs_uuid = None ret = { 'wiki_id': wiki_page._primary_key if wiki_page else None, 'wiki_name': wiki_page.page_name if wiki_page else wiki_name, 'wiki_content': content, 'use_python_render': use_python_render, 'page': wiki_page, 'version': version, 'versions': versions, 'sharejs_uuid': sharejs_uuid or '', 'sharejs_url': settings.SHAREJS_URL, 'is_current': is_current, 'version_settings': version_settings, 'pages_current': _get_wiki_pages_current(node), 'toc': toc, 'category': node.category, 'panels_used': panels_used, 'num_columns': num_columns, 'urls': { 'api': _get_wiki_api_urls(node, wiki_name, { 'content': node.api_url_for('wiki_page_content', wname=wiki_name), 'draft': node.api_url_for('wiki_page_draft', wname=wiki_name), }), 'web': _get_wiki_web_urls(node, wiki_name), 'gravatar': get_gravatar(auth.user, 25), }, } ret.update(_view_project(node, auth, primary=True)) return ret