diff --git a/README-docker-compose.md b/README-docker-compose.md index 32602c21879..0956379333f 100644 --- a/README-docker-compose.md +++ b/README-docker-compose.md @@ -171,7 +171,7 @@ - When starting with an empty database you will need to run migrations and populate preprint providers. See the [Running arbitrary commands](#running-arbitrary-commands) section below for instructions. 6. Start the OSF Web, API Server, and Preprints (Detached) ```bash - docker compose up -d worker web api admin preprints ember_osf_web gv + docker compose up -d worker web api admin preprints gv ``` 7. View the OSF at [http://localhost:5000](http://localhost:5000). @@ -181,7 +181,7 @@ - Once the requirements have all been installed, you can start the OSF in the background with ```bash - docker compose up -d assets admin_assets mfr wb fakecas sharejs worker web api admin preprints ember_osf_web gv + docker compose up -d assets admin_assets mfr wb fakecas sharejs worker web api admin preprints gv ``` - To view the logs for a given container: @@ -270,20 +270,10 @@ ```bash docker compose run --rm web python3 -m scripts.parse_citation_styles ``` -- Populate Notification Types - - Needed for notifications. - ```bash - docker compose run --rm web python3 manage.py populate_notification_types - ``` - - _NOTE: The waffle switch `POPULATE_NOTIFICATION_TYPES` needs to be turned on. -- Start ember_osf_web - - Needed for ember app: - - `docker-compose up -d ember_osf_web` - OPTIONAL: Register OAuth Scopes - - Needed for things such as the ember-osf dummy app - ```bash - docker compose run --rm web python3 -m scripts.register_oauth_scopes - ``` + ```bash + docker compose run --rm web python3 -m scripts.register_oauth_scopes + ``` - OPTIONAL: Create migrations: - After changing a model you will need to create migrations and apply them. Migrations are python code that changes either the structure or the data of a database. This will compare the django models on disk to the database, find the differences, and create migration code to change the database. If there are no changes this command is a noop. ```bash @@ -511,4 +501,4 @@ wb: ### Running Collections -To run collections, you must uncomment COLLECTIONS_ENABLED=true in docker-compose.yml under ember_osf_web, then recreate your ember and web containers. +To run collections, you must uncomment COLLECTIONS_ENABLED=true in docker-compose.yml, then recreate web container. diff --git a/addons/base/views.py b/addons/base/views.py index 5ff3d6e7093..8b4097244b3 100644 --- a/addons/base/views.py +++ b/addons/base/views.py @@ -928,12 +928,12 @@ def addon_view_or_download_file(auth, path, provider, **kwargs): ) ) - # There's no download action redirect to the Ember front-end file view and create guid. + # There's no download action redirect to the front-end file view and create guid. if action != 'download': - if isinstance(target, Node) and flag_is_active(request, features.EMBER_FILE_PROJECT_DETAIL): + if isinstance(target, Node): guid = file_node.get_guid(create=True) return redirect(f'{settings.DOMAIN}{guid._id}/') - if isinstance(target, Registration) and flag_is_active(request, features.EMBER_FILE_REGISTRATION_DETAIL): + if isinstance(target, Registration): guid = file_node.get_guid(create=True) return redirect(f'{settings.DOMAIN}{guid._id}/') diff --git a/addons/osfstorage/tests/test_views.py b/addons/osfstorage/tests/test_views.py index 406024ecad1..825b68b2671 100644 --- a/addons/osfstorage/tests/test_views.py +++ b/addons/osfstorage/tests/test_views.py @@ -36,7 +36,6 @@ from osf_tests.factories import ProjectFactory, ApiOAuth2PersonalTokenFactory, PreprintFactory from website.files.utils import attach_versions -from website.settings import EXTERNAL_EMBER_APPS from api_tests.draft_nodes.views.test_draft_node_files_lists import prepare_mock_wb_response @@ -1413,28 +1412,17 @@ def test_file_view_updates_history(self): {'name': 'testpath', 'path': '/testpath', 'materialized': '/testpath', 'kind': 'file'}, ] ) - with override_flag(features.EMBER_FILE_PROJECT_DETAIL, active=True): - url = self.node.web_url_for('addon_view_or_download_file', path='testpath', provider='github') - self.app.get(url, auth=self.user.auth) - file = GithubFile.objects.get(_path='/testpath', provider='github') - assert file.history - - @mock.patch('website.views.stream_emberapp') - def test_file_views(self, mock_ember): - with override_flag(features.EMBER_FILE_PROJECT_DETAIL, active=True): - file = create_test_file(target=self.node, user=self.user) - url = self.node.web_url_for('addon_view_or_download_file', path=file._id, provider=file.provider) - res = self.app.get(url, auth=self.user.auth) - assert res.status_code == 302 - assert res.headers['Location'] == f'{settings.DOMAIN}{file.get_guid()._id}/' - assert not mock_ember.called - res = self.app.get(url, auth=self.user.auth, follow_redirects=True) - assert res.status_code == 200 - assert mock_ember.called - args, kwargs = mock_ember.call_args - - assert args[0] == EXTERNAL_EMBER_APPS['ember_osf_web']['server'] - assert args[1] == EXTERNAL_EMBER_APPS['ember_osf_web']['path'].rstrip('/') + url = self.node.web_url_for('addon_view_or_download_file', path='testpath', provider='github') + self.app.get(url, auth=self.user.auth) + file = GithubFile.objects.get(_path='/testpath', provider='github') + assert file.history + + def test_file_views(self): + file = create_test_file(target=self.node, user=self.user) + url = self.node.web_url_for('addon_view_or_download_file', path=file._id, provider=file.provider) + res = self.app.get(url, auth=self.user.auth) + assert res.status_code == 302 + assert res.headers['Location'] == f'{settings.DOMAIN}{file.get_guid()._id}/' def test_download_file(self): file = create_test_file(target=self.node, user=self.user) diff --git a/addons/wiki/routes.py b/addons/wiki/routes.py index ed6b1b3a517..1a257d6a07a 100644 --- a/addons/wiki/routes.py +++ b/addons/wiki/routes.py @@ -3,88 +3,18 @@ """ from framework.routing import Rule, json_renderer -from website.routes import OsfWebRenderer from . import views -TEMPLATE_DIR = './addons/wiki/templates/' - settings_routes = { 'rules': [], 'prefix': '/api/v1', } # NOTE: refers to a wiki page's key, e.g. 'Home' +# All HTML-rendered wiki routes have been removed; only API routes remain. page_routes = { - - 'rules': [ - - # Home (Base) | GET - Rule( - [ - '/project//wiki/', - '/project//node//wiki/', - ], - 'get', - views.project_wiki_home, - OsfWebRenderer('edit.mako', trust=False, template_dir=TEMPLATE_DIR) - ), - - # View (ID) | GET - Rule( - [ - '/project//wiki/id//', - '/project//node//wiki/id//', - ], - 'get', - views.project_wiki_id_page, - OsfWebRenderer('edit.mako', trust=False, template_dir=TEMPLATE_DIR) - ), - - # Wiki | GET - Rule( - [ - '/project//wiki//', - '/project//node//wiki//', - ], - 'get', - views.project_wiki_view, - OsfWebRenderer('edit.mako', trust=False, template_dir=TEMPLATE_DIR) - ), - - # Edit | GET (legacy url, trigger redirect) - Rule( - [ - '/project//wiki//edit/', - '/project//node//wiki//edit/', - ], - 'get', - views.project_wiki_edit, - OsfWebRenderer('edit.mako', trust=False, template_dir=TEMPLATE_DIR) - ), - - # Compare | GET (legacy url, trigger redirect) - Rule( - [ - '/project//wiki//compare//', - '/project//node//wiki//compare//', - ], - 'get', - views.project_wiki_compare, - OsfWebRenderer('edit.mako', trust=False, template_dir=TEMPLATE_DIR) - ), - - # Edit | POST - Rule( - [ - '/project//wiki//', - '/project//node//wiki//', - ], - 'post', - views.project_wiki_edit_post, - OsfWebRenderer('edit.mako', trust=False, template_dir=TEMPLATE_DIR) - ), - ] + 'rules': [], } api_routes = { diff --git a/addons/wiki/static/wikiPage.js b/addons/wiki/static/wikiPage.js deleted file mode 100644 index 7ca035b9593..00000000000 --- a/addons/wiki/static/wikiPage.js +++ /dev/null @@ -1,327 +0,0 @@ -'use strict'; -var ko = require('knockout'); -var $ = require('jquery'); - -var $osf = require('js/osfHelpers'); -var mathrender = require('js/mathrender'); -var md = require('js/markdown').full; -var mdQuick = require('js/markdown').quick; -var mdOld = require('js/markdown').old; -var diffTool = require('js/diffTool'); - -var THROTTLE = 500; - -//
-ko.bindingHandlers.mathjaxify = { - update: function(element, valueAccessor, allBindingsAccessor, data, context) { - var vm = context.$data; - //Need to unwrap the data in order for KO to know it's changed. - ko.unwrap(valueAccessor()); - - if(vm.allowMathjaxification() && vm.allowFullRender()) { - mathrender.mathjaxify('#' + element.id); - } - } -}; - - -function ViewWidget(visible, version, viewText, rendered, contentURL, allowMathjaxification, allowFullRender, editor) { - var self = this; - self.version = version; - self.viewText = viewText; // comes from EditWidget.viewText - self.rendered = rendered; - self.visible = visible; - self.allowMathjaxification = allowMathjaxification; - self.editor = editor; - self.allowFullRender = allowFullRender; - self.renderTimeout = null; - self.displaySource = ko.observable(''); - self.debouncedAllowFullRender = $osf.debounce(function() { - self.allowFullRender(true); - }, THROTTLE); - - self.renderMarkdown = function(rawContent){ - if(self.visible()) { - if (self.allowFullRender()) { - return md.render(rawContent); - } else { - return mdQuick.render(rawContent); - } - } else { - return ''; - } - }; - - if (typeof self.editor !== 'undefined') { - self.editor.on('change', function () { - if(self.version() === 'preview') { - // Quick render - self.allowFullRender(false); - - // Full render - self.debouncedAllowFullRender(); - } - }); - } else { - self.allowFullRender(true); - } - - self.displayText = ko.computed(function() { - self.allowFullRender(); - var requestURL; - if (typeof self.version() !== 'undefined') { - if (self.version() === 'preview') { - self.rendered(self.renderMarkdown(self.viewText())); - self.displaySource(self.viewText()); - } else { - if (self.version() === 'current') { - requestURL = contentURL; - } else { - requestURL= contentURL + self.version(); - } - var request = $.ajax({ - url: requestURL - }); - - request.done(function (resp) { - if(self.visible()) { - var $markdownElement = $('#wikiViewRender'); - if (resp.wiki_content){ - var rawContent = resp.wiki_content - } else if(window.contextVars.currentUser.canEdit) { - var rawContent = '*Add important information, links, or images here to describe your project.*'; - } else { - var rawContent = '*No wiki content.*'; - } - if (resp.rendered_before_update) { - // Use old md renderer. Don't mathjaxify - self.allowMathjaxification(false); - self.rendered(mdOld.render(rawContent)); - $markdownElement.css('display', 'inherit'); - - } else { - // Render raw markdown - self.allowMathjaxification(true); - self.rendered(self.renderMarkdown(rawContent)); - $markdownElement.css('display', 'inherit'); - } - self.displaySource(rawContent); - } - }); - } - } else { - self.displaySource(''); - } - }); -} - - // currentText comes from ViewWidget.displayText -function CompareWidget(visible, compareVersion, currentText, rendered, contentURL) { - var self = this; - - self.compareVersion = compareVersion; - self.currentText = currentText; - self.rendered = rendered; - self.visible = visible; - self.contentURL = contentURL; - self.compareSource = ko.observable(''); - - self.compareText = ko.computed(function() { - var requestURL; - if (self.compareVersion() === 'current') { - requestURL = self.contentURL; - } else { - requestURL= self.contentURL + self.compareVersion(); - } - var request = $.ajax({ - url: requestURL - }); - request.done(function (resp) { - var rawText = resp.wiki_content; - self.compareSource(rawText); - }); - - }); - - self.compareOutput = ko.computed(function() { - var output = diffTool.diff(self.compareSource(), self.currentText()); - self.rendered(output); - return output; - }).extend({ notify: 'always' }); - -} - - -var defaultOptions = { - editVisible: false, - viewVisible: true, - compareVisible: false, - menuVisible: true, - canEdit: true, - viewVersion: 'current', - compareVersion: 'previous', - urls: { - content: '', - draft: '', - page: '' - }, - metadata: {} -}; - -function ViewModel(options){ - var self = this; - // enabled? - self.editVis = ko.observable(options.editVisible); - self.viewVis = ko.observable(options.viewVisible); - self.compareVis = ko.observable(options.compareVisible); - self.menuVis = ko.observable(options.menuVisible); - // singleVis : checks if the item visible is the only visible column - self.singleVis = ko.pureComputed(function(){ - var visible = 0; - var single; - if(self.editVis()){ - visible++; - single = 'edit'; - } - if(self.viewVis()){ - visible++; - single = 'view'; - } - if(self.compareVis()){ - visible++; - single = 'compare'; - } - if(visible === 1){ - return single; - } - return false; - }); - - self.pageTitle = $(document).find('title').text(); - - self.compareVersion = ko.observable(options.compareVersion); - self.viewVersion = ko.observable(options.viewVersion); - self.draftURL = options.urls.draft; - self.contentURL = options.urls.content; - self.pageURL = options.urls.page; - self.editorMetadata = options.metadata; - self.canEdit = options.canEdit; - - self.viewText = ko.observable(''); - self.renderedView = ko.observable(''); - self.renderedCompare = ko.observable(''); - self.allowMathjaxification = ko.observable(true); - self.allowFullRender = ko.observable(true); - self.viewVersionDisplay = ko.computed(function() { - var versionString = ''; - if (self.viewVersion() === 'preview') { - versionString = 'Live preview'; - } else if (self.viewVersion() === 'current'){ - versionString = 'Current version'; - } else if (self.viewVersion() === 'previous'){ - versionString = 'Previous version'; - } else { - versionString = 'Version ' + self.viewVersion(); - } - return versionString; - }); - // Save initial query params (except for the "mode" query params, which are handled - // by self.currentURL), so that we can preserve them when we mutate window.history.state - var initialParams = $osf.urlParams(); - delete initialParams.view; - delete initialParams.edit; - delete initialParams.compare; - delete initialParams.menu; - self.initialQueryParams = $.param(initialParams); - - self.currentURL = ko.computed(function() { - // Do not change URL for incompatible browsers - if (typeof window.history.replaceState === 'undefined') { - return; - } - - var paramPrefix = '?'; - var url = self.pageURL; - // Preserve initial query params - if (self.initialQueryParams) { - url += paramPrefix + self.initialQueryParams; - paramPrefix = '&'; - } - // Default view is special cased - if (!self.editVis() && self.viewVis() && self.viewVersion() === 'current' && !self.compareVis() && self.menuVis()) { - window.history.replaceState({}, '', url); - return; - } - - if (self.editVis()) { - url += paramPrefix + 'edit'; - paramPrefix = '&'; - } - if (self.viewVis()) { - url += paramPrefix + 'view'; - paramPrefix = '&'; - if ((!self.editVis() && self.viewVersion() !== 'current' ) || - (self.editVis() && self.viewVersion() !== 'preview')) { - url += '=' + self.viewVersion(); - } - } - if (self.compareVis()) { - url += paramPrefix + 'compare'; - paramPrefix = '&'; - if (self.compareVersion() !== 'previous'){ - url += '=' + self.compareVersion(); - } - } - if (self.menuVis()) { - url += paramPrefix + 'menu'; - } - - window.history.replaceState({}, self.pageTitle, url); - }); - - - if(self.canEdit) { - self.editor = ace.edit('editor'); // jshint ignore: line - - var ShareJSDoc = require('addons/wiki/static/ShareJSDoc.js'); - self.editVM = new ShareJSDoc(self.draftURL, self.editorMetadata, self.viewText, self.editor); - } - self.viewVM = new ViewWidget(self.viewVis, self.viewVersion, self.viewText, self.renderedView, self.contentURL, self.allowMathjaxification, self.allowFullRender, self.editor); - self.compareVM = new CompareWidget(self.compareVis, self.compareVersion, self.viewVM.displaySource, self.renderedCompare, self.contentURL); - - var bodyElement = $('body'); - bodyElement.on('togglePanel', function (event, panel, display) { - // Update self.editVis, self.viewVis, or self.compareVis in viewmodel - self[panel + 'Vis'](display); - //URL needs to be a computed observable, and this should just update the panel states, which will feed URL - // Switch view to correct version - if (panel === 'edit') { - if (display) { - self.viewVersion('preview'); - } else if (self.viewVersion() === 'preview') { - self.viewVersion('current'); - } - } else if (panel === 'view') { - if(!display && self.compareVis() && self.editVis()){ - self.viewVersion('preview'); - } - } - }); - - bodyElement.on('toggleMenu', function(event, menuVisible) { - self.menuVis(menuVisible); - }); -} - - - -var WikiPage = function(selector, options) { - var self = this; - self.options = $.extend({}, defaultOptions, options); - - this.viewModel = new ViewModel(self.options); - $osf.applyBindings(self.viewModel, selector); -}; - -module.exports = WikiPage; - diff --git a/addons/wiki/templates/edit.mako b/addons/wiki/templates/edit.mako deleted file mode 100644 index f9821c3d215..00000000000 --- a/addons/wiki/templates/edit.mako +++ /dev/null @@ -1,417 +0,0 @@ -<%inherit file="project/project_base.mako"/> -<%def name="title()">${node['title']} Wiki - -<%def name="stylesheets()"> - ${parent.stylesheets()} - - -## Use full page width -<%def name="container_class()">container-xxl - -% if (user['can_comment'] or node['has_comments']) and not node['anonymous']: - <%include file="include/comment_pane_template.mako"/> -% endif - -
-
- <%include file="wiki/templates/status.mako"/> -
-
-
-
-
-
-
- -
-
- - -
-
- % if user['can_edit']: -
- New -
- % if wiki_id and wiki_name != 'home': -
- Delete -
- % endif - % else: -

Menu

- % endif - -
-
-
-
-
-
-

Loading wiki pages...

-
-
- -
- - - -
- -
-
-
- -
-
-
-
-
-
View
-
-
- -
- - Wiki Version: -
- -
-
- -
-
-
- -
-
- % if wiki_content: - ${wiki_content} - % else: -

Add important information, links, or images here to describe your project.

- % endif -
-
-
-
- - % if user['can_edit_wiki_body']: -
-
-
-
-
-
-

Edit

-
-
-
-
-
- - - - - - -
-
-
-
- -
-
- - -
-
- -
- % endif - - -
-
-
-
-
- Compare -
- - to - - -
- -
-
-
-
-
-
-
-
-
- -
-
- - - <%include file="wiki/templates/add_wiki_page.mako"/> - <%include file="wiki/templates/wiki-bar-modal-help.mako"/> -% if wiki_id and wiki_name != 'home': - <%include file="wiki/templates/delete_wiki_page.mako"/> -% endif - - - - - - - - - - - - - - - - -<%def name="javascript_bottom()"> -${parent.javascript_bottom()} - - - - - - - diff --git a/addons/wiki/tests/test_wiki.py b/addons/wiki/tests/test_wiki.py index df24ee0690c..f169646e303 100644 --- a/addons/wiki/tests/test_wiki.py +++ b/addons/wiki/tests/test_wiki.py @@ -35,6 +35,10 @@ pytestmark = pytest.mark.django_db + +# TODO: remove all WIKI_WEB_SKIP tests if safe +WIKI_WEB_SKIP = pytest.mark.skip(reason='Wiki web UI removed; served by angular-osf') + # forward slashes are not allowed, typically they would be replaced with spaces SPECIAL_CHARACTERS_ALL = r'`~!@#$%^*()-=_+ []{}\|/?.df,;:''"' SPECIAL_CHARACTERS_ALLOWED = r'`~!@#$%^*()-=_+ []{}\|?.df,;:''"' @@ -54,11 +58,13 @@ def setUp(self): self.second_project = ProjectFactory(is_public=True, creator=self.user) self.sec_wiki = WikiPage.objects.create_for_node(self.second_project, 'home', '', Auth(self.user)) + @WIKI_WEB_SKIP def test_wiki_url_get_returns_200(self): url = self.project.web_url_for('project_wiki_view', wname='home') res = self.app.get(url) assert res.status_code == 200 + @WIKI_WEB_SKIP def test_wiki_url_404_with_no_write_permission(self): # and not public url = self.project.web_url_for('project_wiki_view', wname='somerandomid') res = self.app.get(url, auth=self.user.auth) @@ -66,6 +72,7 @@ def test_wiki_url_404_with_no_write_permission(self): # and not public res = self.app.get(url) assert res.status_code == 404 + @WIKI_WEB_SKIP @mock.patch('addons.wiki.utils.broadcast_to_sharejs') def test_wiki_deleted_404_with_no_write_permission(self, mock_sharejs): url = self.project.web_url_for('project_wiki_view', wname='funpage') @@ -76,6 +83,7 @@ def test_wiki_deleted_404_with_no_write_permission(self, mock_sharejs): res = self.app.get(url) assert res.status_code == 404 + @WIKI_WEB_SKIP def test_wiki_url_with_path_get_returns_200(self): self.funpage_wiki.update(self.user, 'Version 2') @@ -86,6 +94,7 @@ def test_wiki_url_with_path_get_returns_200(self): res = self.app.get(url, auth=self.user.auth) assert res.status_code == 200 + @WIKI_WEB_SKIP def test_wiki_url_with_edit_get_redirects_to_no_edit_params_with_no_write_permission(self): self.funpage_wiki.update(self.user, 'Version 2') @@ -115,6 +124,7 @@ def test_wiki_url_with_edit_get_redirects_to_no_edit_params_with_no_write_permis res = self.app.get(url) assert res.status_code == 401 + @WIKI_WEB_SKIP def test_wiki_url_for_pointer_returns_200(self): # TODO: explain how this tests a pointer project = ProjectFactory(is_public=True) @@ -148,12 +158,14 @@ def test_wiki_content_rendered_before_update(self, mock_rendered_before_update): res = self.app.get(url, auth=self.user.auth) assert not res.json['rendered_before_update'] + @WIKI_WEB_SKIP def test_wiki_url_for_component_returns_200(self): component = NodeFactory(parent=self.project, is_public=True) url = component.web_url_for('project_wiki_view', wname='home') res = self.app.get(url) assert res.status_code == 200 + @WIKI_WEB_SKIP def test_project_wiki_edit_post(self): url = self.project.web_url_for('project_wiki_edit_post', wname='home') res = self.app.post(url, data={'content': 'new content'}, auth=self.user.auth, follow_redirects=True) @@ -163,6 +175,7 @@ def test_project_wiki_edit_post(self): new_wiki = WikiVersion.objects.get_for_node(self.project, 'home') assert new_wiki.content == 'new content' + @WIKI_WEB_SKIP def test_project_wiki_edit_post_with_new_wname_and_no_content(self): # note: forward slashes not allowed in page_name page_name = fake.catch_phrase().replace('/', ' ') @@ -181,6 +194,7 @@ def test_project_wiki_edit_post_with_new_wname_and_no_content(self): new_page = WikiVersion.objects.get_for_node(self.project, page_name) assert new_page is not None + @WIKI_WEB_SKIP def test_project_wiki_edit_post_with_new_wname_and_content(self): # note: forward slashes not allowed in page_name page_name = fake.catch_phrase().replace('/', ' ') @@ -203,6 +217,7 @@ def test_project_wiki_edit_post_with_new_wname_and_content(self): # content was set assert new_page.content == page_content + @WIKI_WEB_SKIP def test_project_wiki_edit_post_with_non_ascii_title(self): # regression test for https://github.com/CenterForOpenScience/openscienceframework.org/issues/1040 # wname doesn't exist in the db, so it will be created @@ -218,6 +233,7 @@ def test_project_wiki_edit_post_with_non_ascii_title(self): res = self.app.post(url, data={'content': 'updated content'}, auth=self.user.auth, follow_redirects=True) assert res.status_code == 200 + @WIKI_WEB_SKIP def test_project_wiki_edit_post_with_special_characters(self): new_wname = 'title: ' + SPECIAL_CHARACTERS_ALLOWED new_wiki_content = 'content: ' + SPECIAL_CHARACTERS_ALL @@ -230,11 +246,13 @@ def test_project_wiki_edit_post_with_special_characters(self): assert wiki.content == new_wiki_content assert res.status_code == 200 + @WIKI_WEB_SKIP def test_wiki_edit_get_home(self): url = self.project.web_url_for('project_wiki_view', wname='home') res = self.app.get(url, auth=self.user.auth) assert res.status_code == 200 + @WIKI_WEB_SKIP def test_project_wiki_view_scope(self): url = self.project.web_url_for('project_wiki_view', wname='home', view=2) res = self.app.get(url, auth=self.user.auth) @@ -246,11 +264,13 @@ def test_project_wiki_view_scope(self): res = self.app.get(url, auth=self.user.auth) assert res.status_code == 400 + @WIKI_WEB_SKIP def test_project_wiki_compare_returns_200(self): url = self.project.web_url_for('project_wiki_view', wname='home') + '?compare' res = self.app.get(url, auth=self.user.auth) assert res.status_code == 200 + @WIKI_WEB_SKIP def test_project_wiki_compare_scope(self): url = self.project.web_url_for('project_wiki_view', wname='home', compare=2) res = self.app.get(url, auth=self.user.auth) @@ -262,6 +282,7 @@ def test_project_wiki_compare_scope(self): res = self.app.get(url, auth=self.user.auth) assert res.status_code == 400 + @WIKI_WEB_SKIP def test_wiki_page_creation_strips_whitespace(self): # Regression test for: # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1080 @@ -321,6 +342,7 @@ def test_project_wiki_validate_name_conflict_different_casing(self): res = self.app.get(url, auth=self.user.auth) assert res.status_code == 409 + @WIKI_WEB_SKIP def test_project_dashboard_shows_no_wiki_content_text(self): # Regression test for: # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104 @@ -341,6 +363,7 @@ def test_project_dashboard_wiki_wname_get_shows_non_ascii_characters(self): res = self.app.get(url, auth=self.user.auth) assert text in res + @WIKI_WEB_SKIP def test_project_wiki_home_api_route(self): url = self.project.api_url_for('project_wiki_home') res = self.app.get(url, auth=self.user.auth) @@ -349,6 +372,7 @@ def test_project_wiki_home_api_route(self): # page_url = self.project.api_url_for('project_wiki_view', wname='home') # assert page_url in res.location + @WIKI_WEB_SKIP def test_project_wiki_home_web_route(self): page_url = self.project.web_url_for('project_wiki_view', wname='home', _guid=True) url = self.project.web_url_for('project_wiki_home') @@ -356,6 +380,7 @@ def test_project_wiki_home_web_route(self): assert res.status_code == 302 assert page_url in res.location + @WIKI_WEB_SKIP def test_wiki_id_url_get_returns_302_and_resolves(self): name = 'page by id' page = WikiPage.objects.create_for_node(self.project, name, 'some content', Auth(self.project.creator)) @@ -368,11 +393,13 @@ def test_wiki_id_url_get_returns_302_and_resolves(self): assert res.status_code == 200 assert page_url in res.request.url + @WIKI_WEB_SKIP def test_wiki_id_url_get_returns_404(self): url = self.project.web_url_for('project_wiki_id_page', wid='12345', _guid=True) res = self.app.get(url) assert res.status_code == 404 + @WIKI_WEB_SKIP def test_home_is_capitalized_in_web_view(self): url = self.project.web_url_for('project_wiki_home', wid='home', _guid=True) res = self.app.get(url, auth=self.user.auth, follow_redirects=True) @@ -424,6 +451,7 @@ def test_wiki_widget_rendered_before_update(self, mock_rendered_before_update): res = serialize_wiki_widget(self.project) assert res['rendered_before_update'] + @WIKI_WEB_SKIP def test_read_only_users_cannot_view_edit_pane(self): url = self.project.web_url_for('project_wiki_view', wname='home') # No write permissions @@ -464,13 +492,6 @@ def setUp(self): self.wname = 'New page' wiki = WikiPage.objects.create_for_node(self.project, self.wname, 'some content', Auth(self.project.creator)) - def test_get_wiki_web_urls(self): - urls = views._get_wiki_web_urls(self.project, self.wname) - assert urls['base'] == self.project.web_url_for('project_wiki_home', _guid=True) - assert urls['edit'] == self.project.web_url_for('project_wiki_view', wname=self.wname, _guid=True) - assert urls['home'] == self.project.web_url_for('project_wiki_home', _guid=True) - assert urls['page'] == self.project.web_url_for('project_wiki_view', wname=self.wname, _guid=True) - def test_get_wiki_api_urls(self): urls = views._get_wiki_api_urls(self.project, self.wname) assert urls['base'] == self.project.api_url_for('project_wiki_home') @@ -743,6 +764,7 @@ def setUp(self): self.wname = 'foo.bar' self.wkey = to_mongo_key(self.wname) + @WIKI_WEB_SKIP def test_uuid_generated_once(self): assert self.project.wiki_private_uuids.get(self.wkey) is None url = self.project.web_url_for('project_wiki_view', wname=self.wname) @@ -761,6 +783,7 @@ def test_uuid_generated_once(self): self.project.reload() assert private_uuid == self.project.wiki_private_uuids.get(self.wkey) + @WIKI_WEB_SKIP def test_uuid_not_visible_without_write_permission(self): WikiPage.objects.create_for_node(self.project, self.wname, 'some content', Auth(self.user)) @@ -780,6 +803,7 @@ def test_uuid_not_visible_without_write_permission(self): assert res.status_code == 200 assert get_sharejs_uuid(self.project, self.wname) not in res.text + @WIKI_WEB_SKIP def test_uuid_not_generated_without_write_permission(self): WikiPage.objects.create_for_node(self.project, self.wname, 'some content', Auth(self.user)) @@ -792,6 +816,7 @@ def test_uuid_not_generated_without_write_permission(self): private_uuid = self.project.wiki_private_uuids.get(self.wkey) assert private_uuid is None + @WIKI_WEB_SKIP def test_uuids_differ_between_pages(self): wname1 = 'foo.bar' url1 = self.project.web_url_for('project_wiki_view', wname=wname1) @@ -813,6 +838,7 @@ def test_uuids_differ_between_pages(self): assert uuid1 not in res2.text assert uuid2 not in res1.text + @WIKI_WEB_SKIP def test_uuids_differ_between_forks(self): url = self.project.web_url_for('project_wiki_view', wname=self.wname) project_res = self.app.get(url, auth=self.user.auth) @@ -852,6 +878,7 @@ def test_migration_does_not_affect_forks(self, mock_sharejs): assert original_uuid != self.project.wiki_private_uuids.get(self.wkey) assert fork.wiki_private_uuids.get(self.wkey) is None + @WIKI_WEB_SKIP @mock.patch('addons.wiki.utils.broadcast_to_sharejs') def test_uuid_persists_after_delete(self, mock_sharejs): assert self.project.wiki_private_uuids.get(self.wkey) is None @@ -881,6 +908,7 @@ def test_uuid_persists_after_delete(self, mock_sharejs): assert original_private_uuid == self.project.wiki_private_uuids.get(self.wkey) assert original_sharejs_uuid in res.text + @WIKI_WEB_SKIP @mock.patch('addons.wiki.utils.broadcast_to_sharejs') def test_uuid_persists_after_rename(self, mock_sharejs): new_wname = 'barbaz' @@ -1269,121 +1297,3 @@ def test_serialize_wiki_settings_disabled_wiki(self): }] assert data == expected - -@pytest.mark.enable_bookmark_creation -class TestWikiMenu(OsfTestCase): - - def setUp(self): - super().setUp() - self.user = UserFactory() - self.project = ProjectFactory(creator=self.user, is_public=True) - self.component = NodeFactory(creator=self.user, parent=self.project, is_public=True) - self.consolidate_auth = Auth(user=self.project.creator) - self.non_contributor = UserFactory() - - def test_format_home_wiki_page_no_content(self): - data = views.format_home_wiki_page(self.project) - expected = { - 'page': { - 'url': self.project.web_url_for('project_wiki_home'), - 'name': 'Home', - 'id': 'None', - } - } - assert data == expected - - def test_format_project_wiki_pages_contributor(self): - home_page = WikiPage.objects.create_for_node(self.project, 'home', 'content here', self.consolidate_auth) - zoo_page = WikiPage.objects.create_for_node(self.project, 'zoo', 'koala', self.consolidate_auth) - data = views.format_project_wiki_pages(self.project, self.consolidate_auth) - expected = [ - { - 'page': { - 'url': self.project.web_url_for('project_wiki_view', wname='home', _guid=True), - 'name': 'Home', - 'id': home_page._primary_key, - } - }, - { - 'page': { - 'url': self.project.web_url_for('project_wiki_view', wname='zoo', _guid=True), - 'name': 'zoo', - 'id': zoo_page._primary_key, - } - } - ] - assert data == expected - - def test_format_project_wiki_pages_no_content_non_contributor(self): - home_page = WikiPage.objects.create_for_node(self.project, 'home', 'content here', self.consolidate_auth) - zoo_page = WikiPage.objects.create_for_node(self.project, 'zoo', '', self.consolidate_auth) - home_page = WikiVersion.objects.get_for_node(self.project, 'home') - data = views.format_project_wiki_pages(self.project, auth=Auth(self.non_contributor)) - expected = [ - { - 'page': { - 'url': self.project.web_url_for('project_wiki_view', wname='home', _guid=True), - 'name': 'Home', - 'id': home_page.wiki_page._primary_key, - } - } - ] - assert data == expected - - def test_format_component_wiki_pages_contributor(self): - home_page = WikiPage.objects.create_for_node(self.component, 'home', 'content here', self.consolidate_auth) - zoo_page = WikiPage.objects.create_for_node(self.component, 'zoo', 'koala', self.consolidate_auth) - expected = [ - { - 'page': { - 'name': self.component.title, - 'url': self.component.web_url_for('project_wiki_view', wname='home', _guid=True), - }, - 'children': [ - { - 'page': { - 'url': self.component.web_url_for('project_wiki_view', wname='home', _guid=True), - 'name': 'Home', - 'id': self.component._primary_key, - } - }, - { - 'page': { - 'url': self.component.web_url_for('project_wiki_view', wname='zoo', _guid=True), - 'name': 'zoo', - 'id': zoo_page._primary_key, - }, - } - ], - 'kind': 'component', - 'category': self.component.category, - 'pointer': False, - } - ] - data = views.format_component_wiki_pages(node=self.project, auth=self.consolidate_auth) - assert data == expected - - def test_format_component_wiki_pages_no_content_non_contributor(self): - data = views.format_component_wiki_pages(node=self.project, auth=Auth(self.non_contributor)) - expected = [] - assert data == expected - - def test_project_wiki_grid_data(self): - WikiPage.objects.create_for_node(self.project, 'home', 'project content', self.consolidate_auth) - WikiPage.objects.create_for_node(self.component, 'home', 'component content', self.consolidate_auth) - data = views.project_wiki_grid_data(auth=self.consolidate_auth, wname='home', node=self.project) - expected = [ - { - 'title': 'Project Wiki Pages', - 'kind': 'folder', - 'type': 'heading', - 'children': views.format_project_wiki_pages(node=self.project, auth=self.consolidate_auth), - }, - { - 'title': 'Component Wiki Pages', - 'kind': 'folder', - 'type': 'heading', - 'children': views.format_component_wiki_pages(node=self.project, auth=self.consolidate_auth) - } - ] - assert data == expected diff --git a/addons/wiki/views.py b/addons/wiki/views.py index 11009c10b07..fed244cd97d 100644 --- a/addons/wiki/views.py +++ b/addons/wiki/views.py @@ -13,11 +13,9 @@ from addons.wiki import settings from addons.wiki import utils as wiki_utils from addons.wiki.models import WikiPage, WikiVersion -from osf import features from website.profile.utils import get_profile_image_url from website.project.views.node import _view_project from website.project.model import has_anonymous_link -from website.ember_osf_web.decorators import ember_flag_is_active from website.project.decorators import ( must_be_contributor_or_public, must_have_addon, must_not_be_registration, @@ -358,7 +356,6 @@ def get_node_wiki_permissions(node, auth, **kwargs): @must_be_valid_project @must_have_addon('wiki', 'node') -@ember_flag_is_active(features.EMBER_PROJECT_WIKI) def project_wiki_home(**kwargs): node = kwargs['node'] or kwargs['project'] return redirect(node.web_url_for('project_wiki_view', wname='home', _guid=True)) diff --git a/admin/institutions/urls.py b/admin/institutions/urls.py index 6aa5cf7e0df..2e260cf4f1b 100644 --- a/admin/institutions/urls.py +++ b/admin/institutions/urls.py @@ -20,5 +20,7 @@ name='list_and_add_admin'), re_path(r'^(?P[0-9]+)/remove_admins/$', views.InstitutionRemoveAdmin.as_view(), name='remove_admins'), + re_path(r'^(?P[0-9]+)/affiliations/$', views.InstitutionListAndAddAffiliation.as_view(), name='affiliations'), + re_path(r'^(?P[0-9]+)/remove_affiliations/$', views.InstitutionRemoveAffiliation.as_view(), name='remove_affiliations'), ] diff --git a/admin/institutions/views.py b/admin/institutions/views.py index 46e6a0a7745..536d916d937 100644 --- a/admin/institutions/views.py +++ b/admin/institutions/views.py @@ -373,3 +373,63 @@ def form_valid(self, form): def get_success_url(self): return reverse('institutions:register_metrics_admin', kwargs={'institution_id': self.kwargs['institution_id']}) + + +class InstitutionAffiliationBaseView(PermissionRequiredMixin, ListView): + permission_required = 'osf.change_institution' + template_name = 'institutions/edit_affiliations.html' + raise_exception = True + + def get_queryset(self): + return Institution.objects.get(id=self.kwargs['institution_id']) + + def get_context_data(self, **kwargs): + institution = Institution.objects.get(id=self.kwargs['institution_id']) + context = super().get_context_data(**kwargs) + context['institution'] = institution + context['affiliations'] = institution.get_institution_users() + return context + + +class InstitutionListAndAddAffiliation(InstitutionAffiliationBaseView): + + def get_permission_required(self): + if self.request.method == 'GET': + return ('osf.view_institution',) + return (self.permission_required,) + + def post(self, request, *args, **kwargs): + institution = Institution.objects.get(id=self.kwargs['institution_id']) + data = dict(request.POST) + del data['csrfmiddlewaretoken'] # just to remove the key from the form dict + + target_user = OSFUser.load(data['add-affiliation-form'][0]) + if target_user is None: + messages.error(request, f'User for guid: {data["add-affiliation-form"][0]} could not be found') + return redirect('institutions:affiliations', institution_id=institution.id) + + target_user.add_or_update_affiliated_institution(institution) + + messages.success(request, f'The following user was successfully added: {target_user.fullname} ({target_user.username})') + + return redirect('institutions:affiliations', institution_id=institution.id) + + +class InstitutionRemoveAffiliation(InstitutionAffiliationBaseView): + + def post(self, request, *args, **kwargs): + institution = Institution.objects.get(id=self.kwargs['institution_id']) + data = dict(request.POST) + del data['csrfmiddlewaretoken'] # just to remove the key from the form dict + + to_be_removed = list(data.keys()) + removed_affiliations = [user.replace('User-', '') for user in to_be_removed if 'User-' in user] + affiliated_users = OSFUser.objects.filter(id__in=removed_affiliations) + for user in affiliated_users: + user.remove_affiliated_institution(institution._id) + + if affiliated_users: + users_names = ' ,'.join(affiliated_users.values_list('fullname', flat=True)) + messages.success(request, f'The following users were successfully removed: {users_names}') + + return redirect('institutions:affiliations', institution_id=institution.id) diff --git a/admin/nodes/urls.py b/admin/nodes/urls.py index ac31ec0dc9b..087a1d57e94 100644 --- a/admin/nodes/urls.py +++ b/admin/nodes/urls.py @@ -50,4 +50,5 @@ re_path(r'^(?P[a-z0-9]+)/system_tags/add/$', views.NodeAddSystemTag.as_view(), name='add-system-tag'), re_path(r'^(?P[a-z0-9]+)/system_tags/(?P[a-z0-9]+)/remove/$', views.NodeRemoveSystemTag.as_view(), name='remove-system-tag'), re_path(r'^(?P[a-z0-9]+)/update_permissions/$', views.NodeUpdatePermissionsView.as_view(), name='update-permissions'), + re_path(r'^(?P[a-z0-9]+)/remove_file/$', views.NodeRemoveFileView.as_view(), name='remove-file'), ] diff --git a/admin/nodes/views.py b/admin/nodes/views.py index 769b3b18d97..01ebad686ce 100644 --- a/admin/nodes/views.py +++ b/admin/nodes/views.py @@ -1,41 +1,43 @@ -import pytz -from enum import Enum from datetime import datetime -from framework import status +from enum import Enum -from django.utils import timezone -from django.core.exceptions import PermissionDenied, ValidationError -from django.urls import NoReverseMatch -from django.db.models import F, Case, When, IntegerField +import pytz +from django.db import transaction from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin +from django.core.exceptions import PermissionDenied, ValidationError +from django.db.models import F, Case, When, IntegerField from django.http import HttpResponse +from django.shortcuts import redirect, reverse, get_object_or_404 +from django.urls import NoReverseMatch +from django.urls import reverse_lazy +from django.utils import timezone from django.views.generic import ( View, FormView, ListView, ) -from django.shortcuts import redirect, reverse, get_object_or_404 -from django.urls import reverse_lazy +from admin.base.forms import GuidForm from admin.base.utils import change_embargo_date from admin.base.views import GuidView -from admin.base.forms import GuidForm -from admin.notifications.views import delete_selected_notifications from admin.nodes.forms import AddSystemTagForm, RegistrationDateForm - -from api.share.utils import update_share +from admin.notifications.views import delete_selected_notifications from api.caching.tasks import update_storage_usage_cache - +from api.share.utils import update_share +from framework import status from osf.exceptions import NodeStateError, RegistrationStuckError +from osf.management.commands.change_node_region import _update_schema_meta from osf.models import ( + Guid, OSFUser, NodeLog, AbstractNode, Registration, RegistrationProvider, RegistrationApproval, - SpamStatus + SpamStatus, + TrashedFile ) from osf.models.admin_log_entry import ( update_admin_log, @@ -49,9 +51,7 @@ REINDEX_ELASTIC, ) from osf.utils.permissions import ADMIN, API_CONTRIBUTOR_PERMISSIONS - from scripts.approve_registrations import approve_past_pendings - from website import settings, search from website.archiver.tasks import force_archive @@ -145,7 +145,8 @@ def get_context_data(self, **kwargs): 'STORAGE_LIMITS': settings.StorageLimits, 'node': node, # to edit contributors we should have guid as django prohibits _id usage as it starts with an underscore - 'annotated_contributors': node.contributor_set.prefetch_related('user__guids').annotate(guid=F('user__guids___id')), + 'annotated_contributors': node.contributor_set.prefetch_related('user__guids').annotate( + guid=F('user__guids___id')), 'children': children, 'permissions': API_CONTRIBUTOR_PERMISSIONS, 'has_update_permission': self.request.user.has_perm('osf.change_node'), @@ -205,7 +206,9 @@ class NodeRemoveContributorView(NodeMixin, View): def post(self, request, *args, **kwargs): node = self.get_object() user = OSFUser.objects.get(id=self.kwargs.get('user_id')) - if node.has_permission(user, ADMIN) and not node._get_admin_contributors_query(node._contributors.all(), require_active=False).exclude(user=user).exists(): + if node.has_permission(user, ADMIN) and not node._get_admin_contributors_query(node._contributors.all(), + require_active=False).exclude( + user=user).exists(): messages.error(self.request, 'Must be at least one admin on this node.') return redirect(self.get_success_url()) @@ -813,6 +816,36 @@ def post(self, request, *args, **kwargs): return redirect(self.get_success_url()) +class NodeRemoveFileView(NodeMixin, View): + """ Allows an authorized user to remove file from node. + """ + permission_required = 'osf.change_node' + + def post(self, request, *args, **kwargs): + def _remove_file_from_schema_response_blocks(registration, removed_file_id): + file_input_keys = registration.registration_schema.schema_blocks.filter( + block_type='file-input' + ).values_list('registration_response_key', flat=True) + for schema_response in registration.schema_responses.all(): + for block in schema_response.response_blocks.filter(schema_key__in=file_input_keys): + if not block.response: + continue + block.response = [entry for entry in block.response if entry.get('file_id') not in removed_file_id] + block.save() + + node = self.get_object() + guid_id = request.POST.get('remove-file-guid', '').strip() + guid = Guid.load(guid_id) + + # delete file from registration and metadata and keep it for original project + if guid and (file := guid.referent) and (file.target == node) and not isinstance(file, TrashedFile): + with transaction.atomic(): + file.delete() + _update_schema_meta(file.target) + _remove_file_from_schema_response_blocks(node, [file._id, file.copied_from._id]) + return redirect(self.get_success_url()) + + class RemoveStuckRegistrationsView(NodeMixin, View): """ Allows an authorized user to remove a registrations if it's stuck in the archiving process. """ @@ -872,6 +905,7 @@ class ForceArchiveRegistrationsView(NodeMixin, View): def post(self, request, *args, **kwargs): # Prevents circular imports that cause admin app to hang at startup from osf.management.commands.force_archive import verify, DEFAULT_PERMISSIBLE_ADDONS + from osf.models.admin_log_entry import update_admin_log, MANUAL_ARCHIVE_RESTART registration = self.get_object() force_archive_params = request.POST @@ -899,16 +933,31 @@ def post(self, request, *args, **kwargs): messages.error(request, str(exc)) return redirect(self.get_success_url()) else: - # For actual archiving, skip synchronous verification to avoid 502 timeouts - # Verification will be performed asynchronously in the task - force_archive_task = force_archive.delay( - str(registration._id), - permissible_addons=list(addons), - allow_unconfigured=allow_unconfigured, - skip_collisions=skip_collision, - delete_collisions=delete_collision, - ) - messages.success(request, f'Registration archive process has started. Task id: {force_archive_task.id}.') + try: + update_admin_log( + user_id=request.user.id, + object_id=registration.pk, + object_repr=str(registration), + message=f'Manual archive restart initiated for registration {registration._id}', + action_flag=MANUAL_ARCHIVE_RESTART + ) + # For actual archiving, skip synchronous verification to avoid 502 timeouts + # Verification will be performed asynchronously in the task + force_archive_task = force_archive.delay( + str(registration._id), + permissible_addons=list(addons), + allow_unconfigured=allow_unconfigured, + skip_collisions=skip_collision, + delete_collisions=delete_collision, + ) + messages.success( + request, + f'Registration archive process has started. Task id: {force_archive_task.id}.' + ) + except Exception as exc: + messages.error(request, + f'This registration cannot be archived due to {exc.__class__.__name__}: {str(exc)}. ' + f'If the problem persists get a developer to fix it.') return redirect(self.get_success_url()) diff --git a/admin/package.json b/admin/package.json index f6655ee92cf..0b4946f491e 100644 --- a/admin/package.json +++ b/admin/package.json @@ -14,6 +14,7 @@ "font-awesome-webpack": "0.0.5-beta.2", "jquery-datetimepicker": "^2.5.21", "json-loader": "^0.5.1", + "keen-dataviz": "^1.0.2", "keen-js": "^3.0.0", "knockout": "3.5.1", "less": "^4.1.2", diff --git a/admin/templates/brands/list.html b/admin/templates/brands/list.html index fcdc512849c..a3d4ec78d6e 100644 --- a/admin/templates/brands/list.html +++ b/admin/templates/brands/list.html @@ -17,12 +17,14 @@

List of Brands

Name + Service - {% for brand in brands %} + {% for brand in brands|dictsort:"name_lower" %} {{ brand.name }} + {{ brand.get_provider_types }} {% endfor %} diff --git a/admin/templates/institutions/detail.html b/admin/templates/institutions/detail.html index 2ce1ad20a03..8c4a9e79e15 100644 --- a/admin/templates/institutions/detail.html +++ b/admin/templates/institutions/detail.html @@ -24,11 +24,12 @@ Delete institution {% endif %} {% if perms.osf.change_institution %} - {% if institution.deactivated is None %} - Deactivate institution - {% else %} - Reactivate institution - {% endif %} + {% if institution.deactivated is None %} + Deactivate institution + {% else %} + Reactivate institution + {% endif %} + Affiliations {% endif %} {% if perms.osf.change_institution %} Manage Admins diff --git a/admin/templates/institutions/edit_affiliations.html b/admin/templates/institutions/edit_affiliations.html new file mode 100644 index 00000000000..e4e25cf1ac6 --- /dev/null +++ b/admin/templates/institutions/edit_affiliations.html @@ -0,0 +1,55 @@ +{% extends "base.html" %} +{% load static %} +{% load render_bundle from webpack_loader %} +{% block title %} + Institution Affiliations +{% endblock title %} +{% block content %} +
+
+ {% if messages %} +
    + {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} +
+
+
+

{{ institution.name }}

+
+
+
+
+
+ {% csrf_token %} + + + +
+
+
+
+
+
+
+ {% csrf_token %} + + + + + {% for user in affiliations %} + + + + + + {% endfor %} +
NameUsername
{{ user.fullname }}{{ user.username }}
+ +
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/admin/templates/nodes/node.html b/admin/templates/nodes/node.html index 1c791ce2b76..3e86290b249 100644 --- a/admin/templates/nodes/node.html +++ b/admin/templates/nodes/node.html @@ -17,6 +17,7 @@ View Logs {% include "nodes/remove_node.html" with node=node %} + {% include "nodes/remove_file.html" with node=node %} {% include "nodes/registration_force_archive.html" with node=node %} {% include "nodes/make_private.html" with node=node %} {% include "nodes/make_public.html" with node=node %} diff --git a/admin/templates/nodes/remove_file.html b/admin/templates/nodes/remove_file.html new file mode 100644 index 00000000000..0f50e39750e --- /dev/null +++ b/admin/templates/nodes/remove_file.html @@ -0,0 +1,36 @@ +{% if node.is_registration and node.archived %} + + Delete File + + +{% endif %} \ No newline at end of file diff --git a/admin/templates/users/affiliated_institutions.html b/admin/templates/users/affiliated_institutions.html new file mode 100644 index 00000000000..2f80ff79350 --- /dev/null +++ b/admin/templates/users/affiliated_institutions.html @@ -0,0 +1,55 @@ +{% extends "base.html" %} +{% load static %} +{% load render_bundle from webpack_loader %} +{% block title %} + Affiliated Institutions +{% endblock title %} +{% block content %} +
+
+ {% if messages %} +
    + {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} +
+
+
+

{{ institution.name }}

+
+
+
+
+
+ {% csrf_token %} + + + +
+
+
+
+
+
+
+ {% csrf_token %} + + + + + {% for institution in institutions %} + + + + + + {% endfor %} +
NameGuid
{{ institution.name }}{{ institution.guid }}
+ +
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/admin/templates/users/user.html b/admin/templates/users/user.html index 96cda4689aa..9bd02221ec7 100644 --- a/admin/templates/users/user.html +++ b/admin/templates/users/user.html @@ -37,7 +37,9 @@ {% include "users/disable_user.html" with user=user %} {% include "users/mark_spam.html" with user=user %} {% include "users/reindex_user_elastic.html" with user=user %} - {% include "users/reindex_user_share.html" with user=user %} + {% if perms.osf.change_institution %} + Affiliations + {% endif %}
diff --git a/admin/users/urls.py b/admin/users/urls.py index 3c87ab1e332..c692c52c4bc 100644 --- a/admin/users/urls.py +++ b/admin/users/urls.py @@ -30,4 +30,6 @@ name='reindex-share-user'), re_path(r'^(?P[a-z0-9]+)/merge_accounts/$', views.UserMergeAccounts.as_view(), name='merge-accounts'), re_path(r'^(?P[a-z0-9]+)/draft_registrations/$', views.UserDraftRegistrationsList.as_view(), name='draft-registrations'), + re_path(r'^(?P[a-z0-9]+)/affiliations/$', views.UserListAndAddAffiliations.as_view(), name='affiliations'), + re_path(r'^(?P[a-z0-9]+)/remove_affiliations/$', views.UserRemoveAffiliations.as_view(), name='remove_affiliations'), ] diff --git a/admin/users/views.py b/admin/users/views.py index fb0cabda15a..be5f6a6d684 100644 --- a/admin/users/views.py +++ b/admin/users/views.py @@ -23,6 +23,7 @@ from osf.models.notification_type import NotificationTypeEnum from framework.auth import get_user from framework.auth.core import generate_verification_key +from osf.models.institution import Institution from website import search from website.settings import EXTERNAL_IDENTITY_PROFILE @@ -49,6 +50,7 @@ from admin.nodes.views import NodeAddSystemTag, NodeRemoveSystemTag from admin.base.views import GuidView from api.users.services import send_password_reset_email +from api.users.tasks import merge_users from website.settings import DOMAIN, OSF_SUPPORT_EMAIL from django.urls import reverse_lazy @@ -215,17 +217,25 @@ def post(self, request, *args, **kwargs): user = self.get_object() user.gdpr_delete() user.save() - messages.success(request, f'User {user._id} was successfully GDPR deleted') - update_admin_log( - user_id=self.request.user.id, - object_id=user.pk, - object_repr='User', - message=f'User {user._id} was successfully GDPR deleted', - action_flag=USER_GDPR_DELETED - ) except UserStateError as e: messages.warning(request, str(e)) + messages.success(request, f'User {user._id} was successfully GDPR deleted') + + # Update SHARE for all public resources + for node in user.nodes.filter(is_public=True, is_deleted=False): + node.update_search() + for preprint in user.preprints.filter(is_public=True, deleted__isnull=True): + preprint.update_search() + + update_admin_log( + user_id=self.request.user.id, + object_id=user.pk, + object_repr='User', + message=f'User {user._id} was successfully GDPR deleted', + action_flag=USER_GDPR_DELETED + ) + return redirect(self.get_success_url()) @@ -416,7 +426,11 @@ def form_valid(self, form): guid_to_be_merged = form.cleaned_data['user_guid_to_be_merged'] user_to_be_merged = OSFUser.objects.get(guids___id=guid_to_be_merged, guids___id__isnull=False) - user.merge_user(user_to_be_merged) + merge_users.delay(user._id, user_to_be_merged._id) + messages.success( + self.request, + f'Merge of user {user_to_be_merged._id} into {user._id} has been queued and will run in the background.', + ) return super().form_valid(form) @@ -622,3 +636,60 @@ def get_context_data(self, **kwargs): 'draft_registrations': query_set } ) + + +class UserAffiliationBaseView(UserMixin, ListView): + permission_required = 'osf.change_institution' + template_name = 'users/affiliated_institutions.html' + raise_exception = True + + def get_queryset(self): + # Django template does not like attributes with underscores for some reason, so we annotate. + return self.get_object().get_affiliated_institutions().annotate( + guid=F('_id') + ) + + def get_context_data(self, **kwargs): + institutions = self.get_queryset() + context = super().get_context_data(**kwargs) + context['institutions'] = institutions + context['user'] = self.get_object() + return context + + +class UserRemoveAffiliations(UserAffiliationBaseView): + + def post(self, request, *args, **kwargs): + user = self.get_object() + data = dict(request.POST) + + to_be_removed = list(data.keys()) + removed_affiliations = [institution.replace('institution-', '') for institution in to_be_removed if 'institution-' in institution] + institutions_qs = Institution.objects.filter(id__in=removed_affiliations) + for institution in institutions_qs: + user.remove_affiliated_institution(institution._id) + + if institutions_qs: + institutions_names = ' ,'.join(institutions_qs.values_list('name', flat=True)) + messages.success(request, f'The following users were successfully removed: {institutions_names}') + + return redirect('users:affiliations', guid=user.guid) + + +class UserListAndAddAffiliations(UserAffiliationBaseView): + + def post(self, request, *args, **kwargs): + user = self.get_object() + data = dict(request.POST) + del data['csrfmiddlewaretoken'] # just to remove the key from the form dict + + institution = Institution.load(data['add-affiliation-form'][0]) + if institution is None: + messages.error(request, f'Institution for guid: {data["add-affiliation-form"][0]} could not be found') + return redirect('users:affiliations', guid=user.guid) + + user.add_or_update_affiliated_institution(institution) + + messages.success(request, f'The following institution was successfully added: {institution.name}') + + return redirect('users:affiliations', guid=user.guid) diff --git a/admin/webpack.admin.config.js b/admin/webpack.admin.config.js index be4bdb6f53d..b1671f4cb7f 100644 --- a/admin/webpack.admin.config.js +++ b/admin/webpack.admin.config.js @@ -43,5 +43,15 @@ var config = Object.assign({}, common, { plugins: plugins, devtool: 'source-map', }); -config.resolve.modules.push(websiteRoot, adminRoot); +config.resolve = Object.assign({}, config.resolve, { + modules: config.resolve.modules.concat([websiteRoot, adminRoot]), + extensions: ['*', '.es6.js', '.js', '.min.js'], +}); + +config.module = Object.assign({}, config.module, { + rules: (config.module && config.module.rules || []).concat([ + {test: /\.es6\.js$/, exclude: [/node_modules/, /bower_components/, /vendor/], loader: 'babel-loader'}, + ]), +}); + module.exports = config; diff --git a/admin/yarn.lock b/admin/yarn.lock index 90252afd898..a31977b47a6 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -35,9 +35,9 @@ ajv-keywords@^3.1.0: integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ajv@^6.1.0: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + version "6.14.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" + integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -88,23 +88,22 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + version "1.5.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.1.tgz#038ab248e4ff078e7bc2485ba6e6388466c78f76" + integrity sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A== dependencies: - object-assign "^4.1.1" - util "0.10.3" + object.assign "^4.1.4" + util "^0.10.4" async@^1.4.0: version "1.5.2" @@ -130,6 +129,13 @@ autoprefixer@^6.3.1: postcss "^5.2.16" postcss-value-parser "^3.2.3" +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -296,14 +302,14 @@ bluebird@^3.5.1: integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + version "4.12.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.3.tgz#2cc2c679188eb35b006f2d0d4710bed8437a769e" + integrity sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g== -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +bn.js@^5.2.1, bn.js@^5.2.2: + version "5.2.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.3.tgz#16a9e409616b23fef3ccbedb8d42f13bff80295e" + integrity sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w== bootstrap-colorpicker@^2.5.2: version "2.5.3" @@ -323,9 +329,9 @@ bower@^1.3.12: integrity sha512-8Rq058FD91q9Nwthyhw0la9fzpBz0iwZTrt51LWl+w+PnJgZk9J+5wp3nibsJcIUPglMYXr4NRBaR+TUj0OkBQ== brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -335,7 +341,7 @@ brorand@^1.0.1, brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -347,7 +353,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-cipher@^1.0.0: +browserify-cipher@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== @@ -366,28 +372,29 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== +browserify-rsa@^4.0.0, browserify-rsa@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.1.tgz#06e530907fe2949dc21fc3c2e2302e10b1437238" + integrity sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ== dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" + bn.js "^5.2.1" + randombytes "^2.1.0" + safe-buffer "^5.2.1" -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== +browserify-sign@^4.2.3: + version "4.2.5" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.5.tgz#3979269fa8af55ba18aac35deef11b45515cd27d" + integrity sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.2" + browserify-rsa "^4.1.1" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.6.1" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.9" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" browserify-versionify@1.0.3: version "1.0.3" @@ -436,6 +443,13 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== +c3@^0.4.18: + version "0.4.24" + resolved "https://registry.yarnpkg.com/c3/-/c3-0.4.24.tgz#57b62357098842d38e265a265f6de1e8c6faadd2" + integrity sha512-mVCFtN5ZWUT5UE7ilFQ7KBQ7TUCdKIq6KsDt1hH/1m6gC1tBjvzFTO7fqhaiWHfhNOjjM7makschdhg6DkWQMA== + dependencies: + d3 "~3.5.0" + cacache@^10.0.4: version "10.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" @@ -455,6 +469,32 @@ cacache@^10.0.4: unique-filename "^1.1.0" y18n "^4.0.0" +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -471,9 +511,9 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30001359" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001359.tgz#6642bf0d654c7db0df413e45d9be9ee15db822a1" - integrity sha512-9c4zPEXTKlVEWtHY5SDVxQZg09US8oyCf7wEPByyGR7T9lKXdhgxMiyS5DWwXaz4cPJiW4zmkM/mUsJSBb9VXw== + version "1.0.30001781" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001781.tgz#7bc16b681ec25e23bd8b2e02067b9cede707c778" + integrity sha512-gNw4Hl6IfkgyGMNzgGRWrnalOUASAYFiCFywQemHI9OU16PC6TRRhHEnR7taYC2/Mad/nDLkzXAEtejGuNsUfg== chalk@^1.1.3: version "1.1.3" @@ -506,12 +546,13 @@ chownr@^1.0.1: integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + version "1.0.7" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.7.tgz#bd094bfef42634ccfd9e13b9fc73274997111e39" + integrity sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.2" clap@^1.0.9: version "1.2.3" @@ -611,9 +652,9 @@ commondir@^1.0.1: integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== component-emitter@^1.1.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" + integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== component-emitter@~1.2.0: version "1.2.1" @@ -646,11 +687,9 @@ constants-browserify@^1.0.0: integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== convert-source-map@^1.5.1: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== cookie@0.3.1: version "0.3.1" @@ -662,12 +701,12 @@ cookiejar@2.0.6: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.0.6.tgz#0abf356ad00d1c5a219d88d44518046dd026acfe" integrity sha512-X9IsySmsr1heROBZCpyEYhqJyU7CXNJoVxIlQ5bBb7DskYUx0mQ+g2f7yPYajceZeGJWHQbIfGB6j0hywV/ARQ== -copy-anything@^2.0.1: - version "2.0.6" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480" - integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw== +copy-anything@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0" + integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== dependencies: - is-what "^3.14.1" + is-what "^4.1.8" copy-concurrently@^1.0.0: version "1.0.5" @@ -691,7 +730,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -create-ecdh@^4.0.0: +create-ecdh@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== @@ -699,7 +738,7 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.5.3" -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: +create-hash@^1.1.0, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -710,7 +749,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -737,21 +776,22 @@ crypt@0.0.2: integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + version "3.12.1" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.1.tgz#bb8921bec9acc81633379aa8f52d69b0b69e0dac" + integrity sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ== dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" + browserify-cipher "^1.0.1" + browserify-sign "^4.2.3" + create-ecdh "^4.0.4" + create-hash "^1.2.0" + create-hmac "^1.1.7" + diffie-hellman "^5.0.3" + hash-base "~3.0.4" + inherits "^2.0.4" + pbkdf2 "^3.1.2" + public-encrypt "^4.0.3" + randombytes "^2.1.0" + randomfill "^1.0.4" css-color-names@0.0.4: version "0.0.4" @@ -838,17 +878,22 @@ csso@~2.3.1: source-map "^0.5.3" cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A== + version "1.0.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.2.tgz#673b5f233bf34d8e602b949429f8171d9121bea3" + integrity sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA== -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== +d3@^3.5.17, d3@~3.5.0: + version "3.5.17" + resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8" + integrity sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg== + +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== dependencies: - es5-ext "^0.10.50" - type "^1.0.1" + es5-ext "^0.10.64" + type "^2.7.2" debug@2, debug@^2.6.8, debug@^2.6.9: version "2.6.9" @@ -857,22 +902,33 @@ debug@2, debug@^2.6.8, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.2.6: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== delayed-stream@~1.0.0: version "1.0.0" @@ -880,9 +936,9 @@ delayed-stream@~1.0.0: integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -894,7 +950,7 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" -diffie-hellman@^5.0.0: +diffie-hellman@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== @@ -913,6 +969,15 @@ domready@0.3.0: resolved "https://registry.yarnpkg.com/domready/-/domready-0.3.0.tgz#b3740facbd09163018152d12aec239383e102175" integrity sha512-0w07yqKSi2caAo0qESL8Ou+ZkDfOrzxyJzSvJEdKmjOzPobPo7d4QFxpLjrq8zmigWP2mh2i/5F53NKSkPIqbA== +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -924,14 +989,14 @@ duplexify@^3.4.2, duplexify@^3.6.0: stream-shift "^1.0.0" electron-to-chromium@^1.2.7: - version "1.4.172" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.172.tgz#87335795a3dc19e7b6dd5af291038477d81dc6b1" - integrity sha512-yDoFfTJnqBAB6hSiPvzmsBJSrjOXJtHSJoqJdI/zSIh7DYupYnIOHt/bbPw/WE31BJjNTybDdNAs21gCMnTh0Q== + version "1.5.322" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.322.tgz#9c24e49f7098ca19bc87c0e9c7e0ad6ffe4fddca" + integrity sha512-vFU34OcrvMcH66T+dYC3G4nURmgfDVewMIu6Q2urXpumAPSMmzvcn04KVVV8Opikq8Vs5nUbO/8laNhNRqSzYw== -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== +elliptic@^6.5.3, elliptic@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -952,9 +1017,9 @@ emojis-list@^3.0.0: integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== dependencies: once "^1.4.0" @@ -976,22 +1041,40 @@ errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: prr "~1.0.1" error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== dependencies: is-arrayish "^0.2.1" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14: - version "0.10.61" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.61.tgz#311de37949ef86b6b0dcea894d1ffedb909d3269" - integrity sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA== +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== dependencies: es6-iterator "^2.0.3" es6-symbol "^3.1.3" + esniff "^2.0.1" next-tick "^1.1.0" -es6-iterator@^2.0.3, es6-iterator@~2.0.1: +es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== @@ -1013,31 +1096,24 @@ es6-map@^0.1.3: event-emitter "~0.3.5" es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha512-7S8YXIcUfPMOr3rqJBVMePAbRsD1nWeSMQ86K/lDI76S3WKXz+KWILvTIPbTroubOkZTGh+b+7/xIIphZXNYbA== + version "0.1.6" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.6.tgz#5669e3b2aa01d61a50ba79964f733673574983b8" + integrity sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw== dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha512-exfuQY8UGtn/N+gL1iKkH8fpNd5sJ760nJq6mmZAHldfxMD5kX07lbQuYlspoXsuknXNv9Fb7y2GsPOnQIbxHg== - dependencies: - d "1" - es5-ext "~0.10.14" + d "^1.0.1" + es5-ext "^0.10.62" + es6-iterator "~2.0.3" + es6-symbol "^3.1.3" + event-emitter "^0.3.5" + type "^2.7.2" es6-symbol@^3.1.1, es6-symbol@^3.1.3, es6-symbol@~3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== dependencies: - d "^1.0.1" - ext "^1.1.2" + d "^1.0.2" + ext "^1.7.0" es6-weak-map@^2.0.1: version "2.0.3" @@ -1064,6 +1140,16 @@ escope@^3.6.0: esrecurse "^4.1.0" estraverse "^4.1.1" +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + esprima@^2.6.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -1091,7 +1177,7 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -event-emitter@~0.3.5: +event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== @@ -1125,12 +1211,12 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== dependencies: - type "^2.5.0" + type "^2.7.2" extend@3.0.0: version "3.0.0" @@ -1217,6 +1303,13 @@ font-awesome@^4.5.0: resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" integrity sha512-U6kGnykA/6bFmg1M/oT9EkFeIYv7JlX3bozwQJWiiLz6L0w3F5vBVPxHlwyX/vtNq1ckcpRKOB9f2Qal/VtFpg== +for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + form-data@1.0.0-rc3: version "1.0.0-rc3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.0-rc3.tgz#d35bc62e7fbc2937ae78f948aaa0d38d90607577" @@ -1254,16 +1347,40 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -1291,10 +1408,15 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== has-ansi@^2.0.0: version "2.0.0" @@ -1318,21 +1440,47 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== -has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - function-bind "^1.1.1" + es-define-property "^1.0.0" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +has@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== + +hash-base@^3.0.0, hash-base@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.2.tgz#79d72def7611c3f6e3c3b5730652638001b10a74" + integrity sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg== dependencies: inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + to-buffer "^1.2.1" + +hash-base@~3.0.4: + version "3.0.5" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" + integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" @@ -1342,6 +1490,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -1431,11 +1586,6 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== - inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -1473,12 +1623,17 @@ is-buffer@~1.1.6: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-core-module@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - has "^1.0.3" + hasown "^2.0.2" is-finite@^1.0.0: version "1.1.0" @@ -1514,10 +1669,17 @@ is-svg@^2.0.0: dependencies: html-comment-regex "^1.1.0" -is-what@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" - integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== +is-typed-array@^1.1.14: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-what@^4.1.8: + version "4.1.16" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f" + integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== isarray@0.0.1: version "0.0.1" @@ -1529,6 +1691,11 @@ isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1544,14 +1711,16 @@ jquery-datetimepicker@^2.5.21: php-date-formatter "^1.3.4" "jquery-mousewheel@>= 3.1.13": - version "3.1.13" - resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" - integrity sha512-GXhSjfOPyDemM005YCEHvzrEALhKDIswtxSHSR2e4K/suHVJKJxxRCGz3skPjNxjJjQa9AVSGGlYjv1M3VLIPg== + version "3.2.2" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.2.2.tgz#48c833f6260ee0c46d438a999e7d0060ec9eed0b" + integrity sha512-JP71xTAg08ZY3hcs9ZbYUZ5i+dkSsz4yRl/zpWkAmtzc+kMs5EfPkpkINSidiLYMaR0MTo3DfFGF9WIezMsFQQ== + dependencies: + jquery ">=1.2.6" -"jquery@>= 1.7.2", jquery@>=1.10: - version "3.6.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" - integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== +"jquery@>= 1.7.2", jquery@>=1.10, jquery@>=1.2.6: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-4.0.0.tgz#95c33ac29005ff72ec444c5ba1cf457e61404fbb" + integrity sha512-TXCHVR3Lb6TZdtw1l3RTLf8RBWVGexdxL6AC8/e0xZKEpBflBsjh9/8LXw+dkNFuOyW9B7iB3O1sP7hS0Kiacg== js-base64@^2.1.9: version "2.6.4" @@ -1602,12 +1771,20 @@ json5@^0.5.0, json5@^0.5.1: integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" +keen-dataviz@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/keen-dataviz/-/keen-dataviz-1.2.1.tgz#6f7595a2051652e1bece2ce2296e47ffa5d79dd9" + integrity sha512-FiWq23fOXfrm+6cCRNpx0FUxtGGzvwb5V9Z0EO1VPaaIrDGMIxvLBjwEAwmLBbeyRRYUHyJFd9XhjSDS9ncpGA== + dependencies: + c3 "^0.4.18" + d3 "^3.5.17" + keen-js@^3.0.0: version "3.5.0" resolved "https://registry.yarnpkg.com/keen-js/-/keen-js-3.5.0.tgz#9274be9bb9ee1a92867872acb3627f5aa8147b79" @@ -1622,9 +1799,9 @@ keen-js@^3.0.0: superagent "^1.8.3" klona@^2.0.4: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + version "2.0.6" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" + integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== knockout@3.5.1: version "3.5.1" @@ -1653,13 +1830,12 @@ less-loader@~2.2.3: loader-utils "^0.2.5" less@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/less/-/less-4.1.3.tgz#175be9ddcbf9b250173e0a00b4d6920a5b770246" - integrity sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA== + version "4.6.4" + resolved "https://registry.yarnpkg.com/less/-/less-4.6.4.tgz#3ff8068e6c8a59f1ece8a6b9227bda28c1ed68a2" + integrity sha512-OJmO5+HxZLLw0RLzkqaNHzcgEAQG7C0y3aMbwtCzIUFZsLMNNq/1IdAdHEycQ58CwUO3jPTHmoN+tE5I7FQxNg== dependencies: - copy-anything "^2.0.1" + copy-anything "^3.0.5" parse-node-version "^1.0.1" - tslib "^2.3.0" optionalDependencies: errno "^0.1.1" graceful-fs "^4.1.2" @@ -1695,9 +1871,9 @@ loader-utils@^0.2.16, loader-utils@^0.2.5: object-assign "^4.0.1" loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -1727,9 +1903,9 @@ lodash.uniq@^4.5.0: integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== lodash@^4.17.14, lodash@^4.17.4: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.17.23" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== loose-envify@^1.0.0: version "1.4.0" @@ -1762,9 +1938,14 @@ make-dir@^2.1.0: semver "^5.6.0" math-expression-evaluator@^1.2.14: - version "1.3.14" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.3.14.tgz#0ebeaccf65fea0f6f5a626f88df41814e5fcd9bf" - integrity sha512-M6AMrvq9bO8uL42KvQHPA2/SbAobA0R7gviUmPrcTcGfdwpaLitz4q2Euzx2lP9Oy88vxK3HOrsISgSwKsYS4A== + version "1.4.0" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.4.0.tgz#3d66031117fbb7b9715ea6c9c68c2cd2eebd37e2" + integrity sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== md5.js@^1.3.4: version "1.3.5" @@ -1850,16 +2031,16 @@ minimalistic-crypto-utils@^1.0.1: integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== minimatch@^3.0.4, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mississippi@^2.0.0: version "2.0.0" @@ -1901,17 +2082,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - needle@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-3.1.0.tgz#3bf5cd090c28eb15644181ab6699e027bd6c53c9" - integrity sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw== + version "3.5.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-3.5.0.tgz#aa2023642cb41b11a11babb733fd8fa952919112" + integrity sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w== dependencies: - debug "^3.2.6" iconv-lite "^0.6.3" sax "^1.2.4" @@ -1996,6 +2171,28 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2065,16 +2262,16 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== +parse-asn1@^5.0.0, parse-asn1@^5.1.9: + version "5.1.9" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.9.tgz#8dd24c3ea8da77dffbc708d94eaf232fd6156e95" + integrity sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg== dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + pbkdf2 "^3.1.5" + safe-buffer "^5.2.1" parse-json@^2.2.0: version "2.2.0" @@ -2127,21 +2324,22 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== +pbkdf2@^3.1.2, pbkdf2@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.5.tgz#444a59d7a259a95536c56e80c89de31cc01ed366" + integrity sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ== dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" + create-hash "^1.2.0" + create-hmac "^1.1.7" + ripemd160 "^2.0.3" + safe-buffer "^5.2.1" + sha.js "^2.4.12" + to-buffer "^1.2.1" php-date-formatter@^1.3.4: - version "1.3.6" - resolved "https://registry.yarnpkg.com/php-date-formatter/-/php-date-formatter-1.3.6.tgz#6d67359da890c742005fa89d20be3ded31cc1d2a" - integrity sha512-/CKsZYmAwXeNh8KpD/CF9hcJDZNhdb2ICN8+qgqOt5sUu9liZIxZ1R284TNj5MtPt8RjG5X0xn6WSqL0kcKMBg== + version "1.3.7" + resolved "https://registry.yarnpkg.com/php-date-formatter/-/php-date-formatter-1.3.7.tgz#915cb587674c5b3ab69884b22a59aedb9c89902d" + integrity sha512-pmHAp3AGz5Ih+TuEJQkmilkB8qWkKYQpnOn93VHzloQQvPFaDqd9vkMOJbLMw2avU6R4/7uPIlfI3A4isvhM3A== pify@^2.0.0: version "2.3.0" @@ -2184,6 +2382,11 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + postcss-calc@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" @@ -2498,7 +2701,7 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== -public-encrypt@^4.0.0: +public-encrypt@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== @@ -2527,20 +2730,15 @@ pumpify@^1.3.3: inherits "^2.0.3" pump "^2.0.0" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - -punycode@^1.2.4: +punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== q@^1.1.2: version "1.5.1" @@ -2552,6 +2750,13 @@ qs@2.3.3: resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" integrity sha512-f5M0HQqZWkzU8GELTY8LyMrGkr3bPjKoFtTkwUEqJQbcljbeK8M7mliP9Ia2xoOI6oMerp+QPS7oYJtpGmWe/A== +qs@^6.12.3: + version "6.15.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.0.tgz#db8fd5d1b1d2d6b5b33adaf87429805f1909e7b3" + integrity sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ== + dependencies: + side-channel "^1.1.0" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -2565,19 +2770,14 @@ querystring-es3@^0.2.0: resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3: +randomfill@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== @@ -2613,10 +2813,10 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.8, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -2646,15 +2846,6 @@ readable-stream@1.0.27-1: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - reduce-component@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/reduce-component/-/reduce-component-1.0.1.tgz#e0c93542c574521bea13df0f9488ed82ab77c5da" @@ -2699,11 +2890,11 @@ require-main-filename@^1.0.1: integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== resolve@^1.10.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -2714,13 +2905,13 @@ rimraf@^2.5.4, rimraf@^2.6.2: dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== +ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.3.tgz#9be54e4ba5e3559c8eee06a25cd7648bbccdf5a8" + integrity sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA== dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" + hash-base "^3.1.2" + inherits "^2.0.4" run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -2729,7 +2920,7 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -2739,12 +2930,17 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@^1.2.4, sax@~1.2.1: +sax@^1.2.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.6.0.tgz#da59637629307b97e7c4cb28e080a7bc38560d5b" + integrity sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA== + +sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -2767,9 +2963,9 @@ schema-utils@^1.0.0: ajv-keywords "^3.1.0" "semver@2 || 3 || 4 || 5", semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== serialize-javascript@^1.4.0: version "1.9.1" @@ -2781,18 +2977,31 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + setimmediate@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== +sha.js@^2.4.0, sha.js@^2.4.12, sha.js@^2.4.8: + version "2.4.12" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" + integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.0" shebang-command@^1.2.0: version "1.2.0" @@ -2806,6 +3015,46 @@ shebang-regex@^1.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + signal-exit@^3.0.0: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -2851,17 +3100,17 @@ source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -2872,9 +3121,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + version "3.0.23" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz#b069e687b1291a32f126893ed76a27a745ee2133" + integrity sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw== spin.js@^2.0.1: version "2.3.2" @@ -2926,9 +3175,9 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== strict-uri-encode@^1.0.0: version "1.1.0" @@ -2952,7 +3201,7 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -3109,6 +3358,15 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== +to-buffer@^1.2.0, to-buffer@^1.2.1, to-buffer@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.2.tgz#ffe59ef7522ada0a2d1cb5dfe03bb8abc3cdc133" + integrity sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw== + dependencies: + isarray "^2.0.5" + safe-buffer "^5.2.1" + typed-array-buffer "^1.0.3" + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -3119,25 +3377,24 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== -tslib@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== -type@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.6.0.tgz#3ca6099af5981d36ca86b78442973694278a219f" - integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" typedarray@^0.0.6: version "0.0.6" @@ -3203,24 +3460,24 @@ urijs@^1.19.7: integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + version "0.11.4" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" + integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== dependencies: - punycode "1.3.2" - querystring "0.2.0" + punycode "^1.4.1" + qs "^6.12.3" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== +util@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: - inherits "2.0.1" + inherits "2.0.3" util@^0.11.0: version "0.11.1" @@ -3253,9 +3510,9 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== watchpack@^1.4.0, watchpack@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + version "2.5.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.1.tgz#dd38b601f669e0cbf567cb802e75cead82cde102" + integrity sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -3310,9 +3567,22 @@ whet.extend@~0.9.9: integrity sha512-mmIPAft2vTgEILgPeZFqE/wWh24SEsR/k+N9fJ3Jxrz44iDFy9aemCxdksfURSHYFCLmvs/d/7Iso5XjPpNfrA== which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.16: + version "1.1.20" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" + integrity sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" which@^1.2.9: version "1.3.1" diff --git a/admin_tests/users/test_views.py b/admin_tests/users/test_views.py index 0e4b6325970..c913a8e2347 100644 --- a/admin_tests/users/test_views.py +++ b/admin_tests/users/test_views.py @@ -672,9 +672,10 @@ class TestUserMerge(AdminTestCase): def setUp(self): super().setUp() self.request = RequestFactory().post('/fake_path') + patch_messages(self.request) - @mock.patch('osf.models.user.OSFUser.merge_user') - def test_merge_user(self, mock_merge_user): + @mock.patch('api.users.tasks.merge_users.delay') + def test_merge_user(self, mock_merge_users_delay): user = UserFactory() user_merged = UserFactory() @@ -688,4 +689,4 @@ def test_merge_user(self, mock_merge_user): assert valid_form.is_valid() view.form_valid(valid_form) - mock_merge_user.assert_called_with(user_merged) + mock_merge_users_delay.assert_called_with(user._id, user_merged._id) diff --git a/api/base/serializers.py b/api/base/serializers.py index b02450f2e12..d5b2c15a95e 100644 --- a/api/base/serializers.py +++ b/api/base/serializers.py @@ -1456,6 +1456,11 @@ class JSONAPISerializer(BaseAPISerializer): @classmethod def many_init(cls, *args, **kwargs): kwargs['child'] = cls(*args, **kwargs) + # Use DRF list_serializer_class if it exists, otherwise use default JSONAPIListSerializer + meta = getattr(cls, 'Meta', None) + list_cls = getattr(meta, 'list_serializer_class', None) + if list_cls: + return list_cls(*args, **kwargs) return JSONAPIListSerializer(*args, **kwargs) def invalid_embeds(self, fields, embeds): diff --git a/api/base/utils.py b/api/base/utils.py index 31bc35fd8d4..6b967760e32 100644 --- a/api/base/utils.py +++ b/api/base/utils.py @@ -155,7 +155,11 @@ def get_object_or_error(model_or_qs, query_or_pk=None, request=None, display_nam if display_name is None: raise Gone else: - raise Gone(detail=f'The requested {display_name} is no longer available.') + AbstractNode = apps.get_model('osf', 'AbstractNode') + spammy_node = isinstance(obj, AbstractNode) and obj.is_spammy + raise Gone( + detail=f'The requested {display_name} is no longer available.', meta={'flagged_content': True} if spammy_node else {}, + ) return obj diff --git a/api/draft_registrations/permissions.py b/api/draft_registrations/permissions.py index 5232ee9d546..fb6829aafa0 100644 --- a/api/draft_registrations/permissions.py +++ b/api/draft_registrations/permissions.py @@ -1,11 +1,13 @@ from rest_framework import permissions +from api.base.exceptions import Conflict from api.base.utils import get_user_auth, assert_resource_type from osf.models import ( DraftRegistration, AbstractNode, DraftRegistrationContributor, OSFUser, + RegistrationProvider, ) from api.nodes.permissions import ContributorDetailPermissions from osf.utils.permissions import WRITE, ADMIN @@ -90,3 +92,32 @@ def has_object_permission(self, request, view, obj): elif isinstance(obj, AbstractNode): return obj.has_permission(auth.user, WRITE) return False + + +class CanSubmitDraftRegistrationToProvider(permissions.BasePermission): + """ + Prevent creating draft registrations for providers that are closed to submissions. + """ + + def has_permission(self, request, view): + if request.method != 'POST': + return True + + provider_id = request.data.get('provider') + + if not provider_id: + try: + provider = RegistrationProvider.get_default() + except RegistrationProvider.DoesNotExist: + return True + else: + try: + provider = RegistrationProvider.objects.get(_id=provider_id) + except RegistrationProvider.DoesNotExist: + # Let existing validation handle bad provider ids. + return True + + if not provider.allow_submissions: + raise Conflict(f"Registry {provider.name} is closed for new submissions. Please start a new registration with a different registry.") + + return True diff --git a/api/draft_registrations/serializers.py b/api/draft_registrations/serializers.py index dbb761d0df1..f08426d32a7 100644 --- a/api/draft_registrations/serializers.py +++ b/api/draft_registrations/serializers.py @@ -98,6 +98,7 @@ class DraftRegistrationSerializer(DraftRegistrationLegacySerializer, Taxonomizab ) has_project = ser.SerializerMethodField() + default_license_id = ser.CharField(source='provider.default_license._id', read_only=True, default='') def get_has_project(self, obj): return obj.has_project @@ -164,6 +165,8 @@ class DraftRegistrationDetailSerializer(DraftRegistrationSerializer, DraftRegist 'self': 'get_self_url', }) + default_license_id = ser.CharField(source='provider.default_license._id', read_only=True, default='') + def get_self_url(self, obj): return absolute_reverse( 'draft_registrations:draft-registration-detail', diff --git a/api/draft_registrations/views.py b/api/draft_registrations/views.py index 30c583dd94a..88a266c9ab6 100644 --- a/api/draft_registrations/views.py +++ b/api/draft_registrations/views.py @@ -8,6 +8,7 @@ DraftContributorDetailPermissions, DraftRegistrationPermission, IsAdminContributor, + CanSubmitDraftRegistrationToProvider, ) from api.draft_registrations.serializers import ( DraftRegistrationSerializer, @@ -53,6 +54,7 @@ class DraftRegistrationList(NodeDraftRegistrationsList): drf_permissions.IsAuthenticatedOrReadOnly, base_permissions.TokenHasScope, DraftRegistrationPermission, + CanSubmitDraftRegistrationToProvider, ) view_category = 'draft_registrations' diff --git a/api/files/views.py b/api/files/views.py index c19aec53d2c..d96289d4010 100644 --- a/api/files/views.py +++ b/api/files/views.py @@ -51,7 +51,7 @@ def get_file(self, check_permissions=True): raise Gone(detail='The requested file is no longer available.') if getattr(obj.target, 'deleted', None): - raise Gone(detail='The requested file is no longer available') + raise Gone(detail='The requested file is no longer available.', meta={'flagged_content': getattr(obj.target, 'is_spammy', False)}) if getattr(obj.target, 'is_retracted', False): raise Gone(detail='The requested file is no longer available.') diff --git a/api/institutions/serializers.py b/api/institutions/serializers.py index 5beffe60348..6f4bc4f9e15 100644 --- a/api/institutions/serializers.py +++ b/api/institutions/serializers.py @@ -231,7 +231,9 @@ class Meta: number_of_users = ser.IntegerField(read_only=True) def get_absolute_url(self, obj): - raise NotImplementedError() + institution_id = self.context['request'].parser_context['kwargs']['institution_id'] + dept_id = obj['name'].replace(' ', '-') + return f'/institutions/{institution_id}/metrics/departments/{dept_id}/' class InstitutionUserMetricsSerializer(JSONAPISerializer): @@ -289,7 +291,8 @@ def get_contacts(self, obj): return list(results) def get_absolute_url(self, obj): - raise NotImplementedError() + institution_id = self.context['request'].parser_context['kwargs']['institution_id'] + return f'/institutions/{institution_id}/metrics/users/' class InstitutionSummaryMetricsSerializer(JSONAPISerializer): @@ -323,7 +326,8 @@ class Meta: ) def get_absolute_url(self, obj): - raise NotImplementedError() + institution_id = self.context['request'].parser_context['kwargs']['institution_id'] + return f'/institutions/{institution_id}/metrics/summary/' class InstitutionRelated(JSONAPIRelationshipSerializer): diff --git a/api/nodes/permissions.py b/api/nodes/permissions.py index 5fc16f6cf16..e7d2b773280 100644 --- a/api/nodes/permissions.py +++ b/api/nodes/permissions.py @@ -127,6 +127,22 @@ def has_object_permission(self, request, view, obj): return obj.has_permission(auth.user, osf_permissions.WRITE) +class AdminOrWriteContributor(permissions.BasePermission): + acceptable_models = (AbstractNode, OSFUser, Institution, BaseAddonSettings, DraftRegistration) + + def has_object_permission(self, request, view, obj): + if isinstance(obj, dict) and 'self' in obj: + obj = obj['self'] + + assert_resource_type(obj, self.acceptable_models) + auth = get_user_auth(request) + + if request.method in permissions.SAFE_METHODS: + return obj.is_public or obj.can_view(auth) + + return obj.has_permission(auth.user, osf_permissions.ADMIN) or obj.has_permission(auth.user, osf_permissions.WRITE) + + class AdminOrPublic(permissions.BasePermission): acceptable_models = (AbstractNode, OSFUser, Institution, BaseAddonSettings, DraftRegistration) diff --git a/api/nodes/serializers.py b/api/nodes/serializers.py index d2bf161043f..1e68d1ff2e4 100644 --- a/api/nodes/serializers.py +++ b/api/nodes/serializers.py @@ -1,3 +1,5 @@ +import functools + from django.db import connection from packaging.version import Version @@ -7,7 +9,7 @@ ) from api.base.serializers import ( VersionedDateTimeField, HideIfRegistration, IDField, - JSONAPISerializer, LinksField, + JSONAPISerializer, JSONAPIListSerializer, LinksField, NodeFileHyperLinkField, RelationshipField, ShowIfVersion, TargetTypeField, TypeField, WaterbutlerLink, BaseAPISerializer, @@ -38,7 +40,7 @@ Comment, DraftRegistration, ExternalAccount, RegistrationSchema, AbstractNode, PrivateLink, Preprint, RegistrationProvider, NodeLicense, DraftNode, - Registration, Node, + Registration, Node, OSFUser, ) from website.project import new_private_link from website.project.model import NodeUpdateError @@ -1219,6 +1221,76 @@ def get_unregistered_contributor(self, obj): return unclaimed_records.get('name', None) +class NodeContributorsBulkCreateListSerializer(JSONAPIListSerializer): + + email_preferences = ['false'] + + def _parse_payload_item(self, item, user_map): + uid = item.get('_id') + user = user_map.get(uid) + email = item.get('user', {}).get('email', None) + full_name = item.get('full_name') or (user.fullname if user and not user.is_registered else None) + if not uid and not full_name: + raise exceptions.ValidationError(detail='A user ID or full name must be provided to add a contributor.') + + email_pref = self.context['request'].GET.get('send_email') or self.context['default_email'] + email_preferences = getattr(self.child, 'email_preferences', self.email_preferences) + if email_pref not in email_preferences: + raise exceptions.ValidationError(f'{email_pref} is not a valid email preference.') + + return { + 'user_id': uid, + 'user': user, + 'email': email, + 'full_name': full_name, + 'notification_type': False if email_pref == 'false' else None, + 'permissions': osf_permissions.get_contributor_proposed_permissions(item), + 'bibliographic': item.get('bibliographic'), + 'index': item.get('_order') if '_order' in item else None, + } + + def _add_contributors_to_node(self, node, payload, auth): + try: + return node.add_contributors_registered_or_not(payload, auth=auth, save=True) + except ValidationError as e: + raise exceptions.ValidationError(detail=e.messages[0]) + except ValueError as e: + raise exceptions.NotFound(detail=e.args[0]) + + def create(self, validated_data): + request = self.context['request'] + node = self.context['resource'] + auth = Auth(request.user) + + # Preload users once and pass through to the bulk method (also reused for children) + user_ids = {item.get('_id') for item in validated_data if item.get('_id')} + user_map = {} + if user_ids: + for u in OSFUser.objects.filter(guids___id__in=user_ids): + user_map[u._id] = u + + _parse_payload_item = functools.partial(self._parse_payload_item, user_map=user_map) + + payload = list(map(_parse_payload_item, validated_data)) + contribs = self._add_contributors_to_node(node, payload, auth) + + child_to_items = {} + for item in validated_data: + child_nodes = item.get('child_nodes') + if child_nodes: + for child_id in child_nodes: + child_to_items.setdefault(child_id, []).append(item) + + for child_id, items in child_to_items.items(): + child = AbstractNode.load(child_id) + if not child: + continue + child_payload = list(map(_parse_payload_item, items)) + self._add_contributors_to_node(child, child_payload, auth) + + return contribs + + class NodeContributorsCreateSerializer(NodeContributorsSerializer): """ Overrides NodeContributorsSerializer to add email, full_name, send_email, and non-required index and users field. @@ -1239,8 +1311,8 @@ class NodeContributorsCreateSerializer(NodeContributorsSerializer): email_preferences = ['default', 'false'] - def get_proposed_permissions(self, validated_data): - return validated_data.get('permission') or osf_permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS + class Meta(NodeContributorsSerializer.Meta): + list_serializer_class = NodeContributorsBulkCreateListSerializer def validate_data(self, resource, user_id=None, full_name=None, email=None, index=None, child_nodes=None): if not user_id and not full_name: @@ -1263,7 +1335,7 @@ def create(self, validated_data): email_pref = self.context['request'].GET.get('send_email') or self.context['default_email'] child_nodes = validated_data.get('child_nodes') - permissions = self.get_proposed_permissions(validated_data) + permissions = osf_permissions.get_contributor_proposed_permissions(validated_data) self.validate_data(resource, user_id=user_id, full_name=full_name, email=email, index=index, child_nodes=child_nodes) if email_pref not in self.email_preferences: diff --git a/api/nodes/views.py b/api/nodes/views.py index 220cc4fb5de..931220a6f88 100644 --- a/api/nodes/views.py +++ b/api/nodes/views.py @@ -9,7 +9,8 @@ from osf import features from packaging.version import Version from django.apps import apps -from django.db.models import F, Max, Q, Subquery +from django.db.models import F, Max, Q, Subquery, Exists, OuterRef +from django.db import transaction from django.utils import timezone from django.contrib.contenttypes.models import ContentType from rest_framework import generics, permissions as drf_permissions, exceptions @@ -73,7 +74,10 @@ NodeCommentSerializer, ) from api.draft_registrations.serializers import DraftRegistrationSerializer, DraftRegistrationDetailSerializer -from api.draft_registrations.permissions import DraftRegistrationPermission +from api.draft_registrations.permissions import ( + DraftRegistrationPermission, + CanSubmitDraftRegistrationToProvider, +) from api.files.serializers import FileSerializer, OsfStorageFileSerializer from api.files import annotations as file_annotations from api.identifiers.serializers import NodeIdentifierSerializer @@ -97,6 +101,7 @@ NodeLinksShowIfVersion, ReadOnlyIfWithdrawn, ) +from osf.utils import permissions as osf_permissions from api.nodes.serializers import ( NodeSerializer, ForwardNodeAddonSettingsSerializer, @@ -155,6 +160,7 @@ CedarMetadataRecord, Preprint, Collection, + Contributor, NotificationTypeEnum, ) from addons.osfstorage.models import Region @@ -551,13 +557,30 @@ def perform_destroy(self, instance): auth = get_user_auth(self.request) if node.visible_contributors.count() == 1 and instance.visible: raise ValidationError('Must have at least one visible contributor') - removed = node.remove_contributor(instance, auth) - if not removed: - raise ValidationError('Must have at least one registered admin contributor') - propagate = self.request.query_params.get('propagate_to_children') == 'true' - if propagate: - for child_node in node.get_nodes(_contributors__in=[instance.user]): - child_node.remove_contributor(instance, auth) + + include_children = is_truthy(self.request.query_params.get('include_children', False)) + + if include_children and isinstance(node, Node): + hierarchy = Node.objects.get_children(node, active=True, include_root=True) + targets = hierarchy.filter( + Exists( + Contributor.objects.filter( + node=OuterRef('pk'), + user=instance.user, + ), + ), + ) + with transaction.atomic(): + for descendant in targets: + if not descendant.has_permission(auth.user, osf_permissions.ADMIN): + raise PermissionDenied(f'Must have admin permission on {descendant._id} to remove contributor.') + removed = descendant.remove_contributor(instance, auth) + if not removed: + raise ValidationError(f'{descendant._id} must have at least one registered admin contributor') + else: + removed = node.remove_contributor(instance, auth) + if not removed: + raise ValidationError('Must have at least one registered admin contributor') class NodeImplicitContributorsList(JSONAPIBaseView, generics.ListAPIView, ListFilterMixin, NodeMixin): @@ -651,6 +674,7 @@ class NodeDraftRegistrationsList(JSONAPIBaseView, generics.ListCreateAPIView, No DraftRegistrationPermission, drf_permissions.IsAuthenticatedOrReadOnly, base_permissions.TokenHasScope, + CanSubmitDraftRegistrationToProvider, ) parser_classes = (JSONAPIMultipleRelationshipsParser, JSONAPIMultipleRelationshipsParserForRegularJSON) diff --git a/api/preprints/serializers.py b/api/preprints/serializers.py index 4c9c9214924..b901aa093f3 100644 --- a/api/preprints/serializers.py +++ b/api/preprints/serializers.py @@ -256,6 +256,7 @@ class PreprintSerializer(TaxonomizableSerializerMixin, MetricsSerializerMixin, J why_no_prereg = ser.CharField(required=False, allow_blank=True, allow_null=True) prereg_links = ser.ListField(child=ser.URLField(), required=False) prereg_link_info = ser.ChoiceField(Preprint.PREREG_LINK_INFO_CHOICES, required=False, allow_blank=True) + default_license_id = ser.CharField(source='provider.default_license._id', read_only=True, default='') class Meta: type_ = 'preprints' diff --git a/api/preprints/views.py b/api/preprints/views.py index 38bcce4c3f1..35bc61aa9d5 100644 --- a/api/preprints/views.py +++ b/api/preprints/views.py @@ -22,7 +22,7 @@ from api.actions.serializers import ReviewActionSerializer from api.actions.views import get_review_actions_queryset from api.base.pagination import PreprintContributorPagination -from api.base.exceptions import Conflict +from api.base.exceptions import Conflict, Gone from api.base.views import JSONAPIBaseView, WaterButlerMixin from api.base.filters import ListFilterMixin, PreprintAsTargetFilterMixin, PreprintFilterMixin from api.base.parsers import ( @@ -126,20 +126,19 @@ def get_preprint(self, check_object_permissions=True, ignore_404=False): qs = Preprint.published_objects.filter(versioned_guids__guid___id=base_guid_id).order_by('-versioned_guids__version') preprint = qs.select_for_update().first() if check_select_for_update(self.request) else qs.select_related('node').first() + user = self.request.user if not preprint: sentry.log_message(f'Preprint not found: [guid={base_guid_id}, version={preprint_version}]') if ignore_404: return raise NotFound if preprint.deleted is not None: - sentry.log_message(f'Preprint deleted: [guid={base_guid_id}, version={preprint_version}]') - raise NotFound - - # May raise a permission denied - if check_object_permissions: - self.check_object_permissions(self.request, preprint) + if preprint.is_spammy: + raise Gone(detail='The requested preprint is no longer available.', meta={'flagged_content': True}) + else: + sentry.log_message(f'Preprint deleted: [guid={base_guid_id}, version={preprint_version}]') + raise Gone(detail='The requested preprint is no longer available.') - user = self.request.user if isinstance(user, AnonymousUser): user_is_reviewer = user_is_contributor = False else: @@ -162,8 +161,15 @@ def get_preprint(self, check_object_permissions=True, ignore_404=False): raise PermissionDenied( detail='This preprint is pending moderation and is not yet publicly available.', ) + # May raise a permission denied + if check_object_permissions: + self.check_object_permissions(self.request, preprint) raise NotFound + # May raise a permission denied + if check_object_permissions: + self.check_object_permissions(self.request, preprint) + return preprint class PreprintList(PreprintMetricsViewMixin, JSONAPIBaseView, generics.ListCreateAPIView, PreprintFilterMixin): diff --git a/api/providers/serializers.py b/api/providers/serializers.py index 3ab0e003ba2..7431d221fef 100644 --- a/api/providers/serializers.py +++ b/api/providers/serializers.py @@ -138,6 +138,11 @@ class Meta: 'name', ]) + default_license_id = ser.SerializerMethodField(read_only=True) + + def get_default_license_id(self, obj): + return obj.default_license._id if obj.default_license else None + class RegistrationProviderSerializer(ProviderSerializer): class Meta: type_ = 'registration-providers' diff --git a/api/registrations/views.py b/api/registrations/views.py index b80bc0afede..67705b5eace 100644 --- a/api/registrations/views.py +++ b/api/registrations/views.py @@ -60,6 +60,7 @@ AdminOrPublic, ExcludeWithdrawals, NodeLinksShowIfVersion, + AdminOrWriteContributor, ) from api.registrations.permissions import ContributorOrModerator, ContributorOrModeratorOrPublic from api.registrations.serializers import ( @@ -122,7 +123,7 @@ def get_node(self, check_object_permissions=True, **annotations): raise NotFound if node.deleted: - raise Gone(detail='The requested registration is no longer available.') + raise Gone(detail='The requested registration is no longer available.', meta={'flagged_content': node.is_spammy}) if check_object_permissions: self.check_object_permissions(self.request, node) @@ -697,7 +698,7 @@ class RegistrationInstitutionsRelationship(NodeInstitutionsRelationship, Registr permission_classes = ( drf_permissions.IsAuthenticatedOrReadOnly, base_permissions.TokenHasScope, - AdminOrPublic, + AdminOrWriteContributor, ) diff --git a/api/sparse/serializers.py b/api/sparse/serializers.py index a085b7344ec..97142771296 100644 --- a/api/sparse/serializers.py +++ b/api/sparse/serializers.py @@ -23,7 +23,7 @@ class SparseNodeSerializer(NodeSerializer): 'contributors', ]) links = LinksField({ - 'self': 'get_absolute_url', # self links will break ember data unless we make a specific sparse detail serializer + 'self': 'get_absolute_url', 'html': 'get_absolute_html_url', }) detail = RelationshipField( @@ -109,7 +109,7 @@ class SparseRegistrationSerializer(RegistrationSerializer): ]) links = LinksField({ - 'self': 'get_absolute_url', # self links will break ember data unless we make a specific sparse detail serializer + 'self': 'get_absolute_url', 'html': 'get_absolute_html_url', }) detail = RelationshipField( diff --git a/api/users/tasks.py b/api/users/tasks.py new file mode 100644 index 00000000000..e11ef0665e9 --- /dev/null +++ b/api/users/tasks.py @@ -0,0 +1,34 @@ +import logging + +from framework import sentry +from framework.celery_tasks import app as celery_app + +logger = logging.getLogger(__name__) + + +@celery_app.task(name='api.users.tasks.merge_users') +def merge_users(merger_guid: str, mergee_guid: str): + """ + Background task to merge one user into another. + + :param merger_guid: GUID of the primary user that will receive content + :param mergee_guid: GUID of the user being merged into the primary user + """ + from osf.models import OSFUser + + try: + merger = OSFUser.load(merger_guid) + mergee = OSFUser.load(mergee_guid) + + if not merger or not mergee: + sentry.log_message(f'User merge task received invalid users: merger={merger_guid}, mergee={mergee_guid}') + return + + if merger == mergee: + sentry.log_message(f'User merge task attempted to merge a user into itself: {merger_guid}') + return + + merger.merge_user(mergee) + except Exception as exc: + logger.exception(f'Unexpected error during background user merge: merger={merger_guid}, mergee={mergee_guid}') + sentry.log_exception(exc) diff --git a/api_tests/draft_registrations/views/test_draft_registration_contributor_detail.py b/api_tests/draft_registrations/views/test_draft_registration_contributor_detail.py index 0c2dce3501b..b60527b7780 100644 --- a/api_tests/draft_registrations/views/test_draft_registration_contributor_detail.py +++ b/api_tests/draft_registrations/views/test_draft_registration_contributor_detail.py @@ -8,12 +8,14 @@ ) from api_tests.nodes.views.test_node_contributors_detail_ordering import TestNodeContributorOrdering from api_tests.nodes.views.test_node_contributors_detail_update import TestNodeContributorUpdate +from api_tests.utils import disconnected_from_listeners from osf_tests.factories import ( DraftRegistrationFactory, ProjectFactory, AuthUserFactory ) from osf.utils import permissions +from website.project.signals import contributor_removed @pytest.fixture() @@ -251,6 +253,43 @@ def url_user_non_contrib(self, project, user_non_contrib): return '/{}draft_registrations/{}/contributors/{}/'.format( API_BASE, project._id, user_non_contrib._id) + def test_remove_contributor_include_children_removes_descendants(self, app, user, user_write_contrib, project): + assert user_write_contrib in project.contributors + + url = f'/{API_BASE}draft_registrations/{project._id}/contributors/{user_write_contrib._id}/?include_children=true' + with disconnected_from_listeners(contributor_removed): + res = app.delete(url, auth=user.auth) + assert res.status_code == 204 + + project.reload() + assert user_write_contrib not in project.contributors + + def test_remove_contributor_include_children_is_atomic_on_violation(self, app, user, user_write_contrib, project): + assert user_write_contrib in project.contributors + + # Draft registrations don't have children, so include_children parameter is ignored + # The contributor should be removed successfully since there are no children to cause violations + url = f'/{API_BASE}draft_registrations/{project._id}/contributors/{user_write_contrib._id}/?include_children=true' + with disconnected_from_listeners(contributor_removed): + res = app.delete(url, auth=user.auth) + assert res.status_code == 204 + + project.reload() + assert user_write_contrib not in project.contributors + + def test_remove_contributor_include_children_forbidden_if_unauthorized_child(self, app, user, user_write_contrib, project): + # Draft registrations have no child components, so include_children does not + # trigger any descendant permission checks; the contributor is simply removed. + assert user_write_contrib in project.contributors + + url = f'/{API_BASE}draft_registrations/{project._id}/contributors/{user_write_contrib._id}/?include_children=true' + with disconnected_from_listeners(contributor_removed): + res = app.delete(url, auth=user.auth) + assert res.status_code == 204 + + project.reload() + assert user_write_contrib not in project.contributors + @pytest.mark.django_db class TestDraftBibliographicContributorDetail(): diff --git a/api_tests/draft_registrations/views/test_draft_registration_list.py b/api_tests/draft_registrations/views/test_draft_registration_list.py index 7e0ebf92e3c..decb75e087e 100644 --- a/api_tests/draft_registrations/views/test_draft_registration_list.py +++ b/api_tests/draft_registrations/views/test_draft_registration_list.py @@ -399,6 +399,19 @@ def test_affiliated_institutions_are_copied_from_user(self, app, user, url_draft draft_registration = DraftRegistration.load(res.json['data']['id']) assert list(draft_registration.affiliated_institutions.all()) == list(user.get_affiliated_institutions()) + def test_cannot_create_draft_when_provider_disallows_submissions( + self, app, user, provider, payload, url_draft_registrations): + provider.allow_submissions = False + provider.save() + + res = app.post_json_api( + url_draft_registrations, + payload, + auth=user.auth, + expect_errors=True, + ) + assert res.status_code == 409 + class TestDraftRegistrationCreateWithoutNode(AbstractDraftRegistrationTestCase): @pytest.fixture() @@ -451,6 +464,19 @@ def test_create_draft_with_provider( draft = DraftRegistration.load(data['id']) assert draft.provider == non_default_provider + def test_cannot_create_draft_when_provider_disallows_submissions( + self, app, user, url_draft_registrations, non_default_provider, payload_with_non_default_provider): + non_default_provider.allow_submissions = False + non_default_provider.save() + + res = app.post_json_api( + url_draft_registrations, + payload_with_non_default_provider, + auth=user.auth, + expect_errors=True, + ) + assert res.status_code == 409 + def test_write_contrib(self, app, user, project_public, payload, url_draft_registrations, user_write_contrib): """(no node supplied, so any logged in user can create) """ diff --git a/api_tests/files/views/test_file_detail.py b/api_tests/files/views/test_file_detail.py index 45d3888dcc3..e9f432d60d1 100644 --- a/api_tests/files/views/test_file_detail.py +++ b/api_tests/files/views/test_file_detail.py @@ -607,6 +607,24 @@ def test_folder_files_relationships_contains_guid_not_id( assert node._id in split_href assert node.id not in split_href + def test_spammed_node_file_detail_gone(self, app, node, file_url, user): + node.confirm_spam(save=True, train_spam_services=False) + res = app.get(file_url, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested file is no longer available.' + assert 'meta' in error + assert error['meta']['flagged_content'] + + def test_deleted_file_not_spammed_gone(self, app, user, file, file_url): + file.delete(user=user, save=True) + res = app.get(file_url, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested file is no longer available.' + assert 'meta' in error + assert not error['meta'].get('flagged_content', False) + @pytest.mark.django_db class TestFileVersionView: diff --git a/api_tests/identifiers/views/test_identifier_list.py b/api_tests/identifiers/views/test_identifier_list.py index 95277a38a13..7a117b4e6f4 100644 --- a/api_tests/identifiers/views/test_identifier_list.py +++ b/api_tests/identifiers/views/test_identifier_list.py @@ -380,26 +380,26 @@ def test_preprint_identifier_list_permissions_deleted( # test_unpublished_preprint_identifier_unauthenticated res = app.get(url_preprint_identifier, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_unpublished_preprint_identifier_noncontrib_authenticated non_contrib = AuthUserFactory() res = app.get(url_preprint_identifier, auth=non_contrib.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_unpublished_preprint_identifier_admin_authenticated res = app.get(url_preprint_identifier, auth=user.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_unpublished_preprint_identifier_readcontrib_authenticated read_user = AuthUserFactory() preprint.add_contributor(read_user, READ, save=True) res = app.get(url_preprint_identifier, auth=read_user.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_published_preprint_identifier_unauthenticated res = app.get(url_preprint_identifier, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 def test_preprint_identifier_list_permissions_abandoned( self, app, user, data_preprint_identifier, preprint, url_preprint_identifier): diff --git a/api_tests/nodes/views/test_node_contributors_detail.py b/api_tests/nodes/views/test_node_contributors_detail.py index 5dc600279ba..0f5435df52e 100644 --- a/api_tests/nodes/views/test_node_contributors_detail.py +++ b/api_tests/nodes/views/test_node_contributors_detail.py @@ -457,3 +457,68 @@ def test_can_remove_self_as_contributor_not_unique_admin(self, app, user_write_c ) assert res.status_code == 204 assert user_write_contrib not in project.contributors + + def test_remove_contributor_include_children_removes_descendants(self, app, user, user_write_contrib, project): + child1 = ProjectFactory(parent=project, creator=user) + child2 = ProjectFactory(parent=project, creator=user) + child1.add_contributor(user_write_contrib, permissions=permissions.WRITE, visible=True, save=True) + child2.add_contributor(user_write_contrib, permissions=permissions.WRITE, visible=True, save=True) + + assert user_write_contrib in project.contributors + assert user_write_contrib in child1.contributors + assert user_write_contrib in child2.contributors + + url = f'/{API_BASE}nodes/{project._id}/contributors/{user_write_contrib._id}/?include_children=true' + with disconnected_from_listeners(contributor_removed): + res = app.delete(url, auth=user.auth) + assert res.status_code == 204 + + project.reload() + child1.reload() + child2.reload() + + assert user_write_contrib not in project.contributors + assert user_write_contrib not in child1.contributors + assert user_write_contrib not in child2.contributors + + def test_remove_contributor_include_children_is_atomic_on_violation(self, app, user, user_write_contrib, project): + child = ProjectFactory(parent=project, creator=user) + child.add_contributor(user_write_contrib, permissions=permissions.ADMIN, visible=True, save=True) + child.set_permissions(user, permissions.READ, save=True) + + assert user_write_contrib in project.contributors + assert user_write_contrib in child.contributors + + url = f'/{API_BASE}nodes/{project._id}/contributors/{user_write_contrib._id}/?include_children=true' + with disconnected_from_listeners(contributor_removed): + res = app.delete(url, auth=user.auth, expect_errors=True) + + assert res.status_code == 403 + + project.reload() + child.reload() + + assert user_write_contrib in project.contributors + assert user_write_contrib in child.contributors + + def test_remove_contributor_include_children_forbidden_if_unauthorized_child(self, app, user, user_write_contrib, project): + other_admin = AuthUserFactory() + child = ProjectFactory(parent=project, creator=other_admin) + child.add_contributor(user_write_contrib, permissions=permissions.WRITE, visible=True, save=True) + + assert user in project.contributors + assert user not in child.contributors + assert other_admin in child.contributors + assert user_write_contrib in project.contributors + assert user_write_contrib in child.contributors + + url = f'/{API_BASE}nodes/{project._id}/contributors/{user_write_contrib._id}/?include_children=true' + with disconnected_from_listeners(contributor_removed): + res = app.delete(url, auth=user.auth, expect_errors=True) + assert res.status_code == 403 + + project.reload() + child.reload() + + assert user_write_contrib in project.contributors + assert user_write_contrib in child.contributors diff --git a/api_tests/nodes/views/test_node_detail.py b/api_tests/nodes/views/test_node_detail.py index 5fa0cd8e150..e03cff83ca9 100644 --- a/api_tests/nodes/views/test_node_detail.py +++ b/api_tests/nodes/views/test_node_detail.py @@ -571,3 +571,22 @@ def test_current_user_permissions_vol(self, app, user, url_public, project_publi private_link.save() res = app.get(f'{url_public}?view_only={private_link.key}', auth=user.auth) assert [permissions.READ] == res.json['data']['attributes']['current_user_permissions'] + + def test_spammed_node_detail_gone(self, app, user, project_public, url_public): + project_public.confirm_spam(save=True, train_spam_services=False) + res = app.get(url_public, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested node is no longer available.' + assert 'meta' in error + assert error['meta']['flagged_content'] + + def test_not_spammed_deleted_node_detail_gone(self, app, user, project_public, url_public): + project_public.is_deleted = True + project_public.save() + res = app.get(url_public, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested node is no longer available.' + assert 'meta' in error + assert not error['meta'].get('flagged_content', False) diff --git a/api_tests/preprints/views/test_preprint_citations.py b/api_tests/preprints/views/test_preprint_citations.py index a95f7527d2f..4fa6fe69be3 100644 --- a/api_tests/preprints/views/test_preprint_citations.py +++ b/api_tests/preprints/views/test_preprint_citations.py @@ -122,21 +122,21 @@ def test_deleted_preprint_citations(self): # Unauthenticated res = self.app.get(self.published_preprint_url, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Non contrib res = self.app.get(self.published_preprint_url, auth=self.other_contrib.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Write contrib self.published_preprint.add_contributor(self.other_contrib, WRITE, save=True) res = self.app.get(self.published_preprint_url, auth=self.other_contrib.auth, expect_errors=True) # Really because preprint is in initial machine state - assert res.status_code == 404 + assert res.status_code == 410 # Admin contrib res = self.app.get(self.published_preprint_url, auth=self.admin_contributor.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 def test_abandoned_preprint_citations(self): self.published_preprint.machine_state = DefaultStates.INITIAL.value @@ -243,21 +243,21 @@ def test_deleted_preprint_citations(self): # Unauthenticated res = self.app.get(self.published_preprint_url, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Non contrib res = self.app.get(self.published_preprint_url, auth=self.other_contrib.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Write contrib self.published_preprint.add_contributor(self.other_contrib, WRITE, save=True) res = self.app.get(self.published_preprint_url, auth=self.other_contrib.auth, expect_errors=True) # Really because preprint is in initial machine state - assert res.status_code == 404 + assert res.status_code == 410 # Admin contrib res = self.app.get(self.published_preprint_url, auth=self.admin_contributor.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 def test_abandoned_preprint_citations(self): self.published_preprint.machine_state = DefaultStates.INITIAL.value diff --git a/api_tests/preprints/views/test_preprint_contributors_detail.py b/api_tests/preprints/views/test_preprint_contributors_detail.py index 726656fda75..e052c4eb62d 100644 --- a/api_tests/preprints/views/test_preprint_contributors_detail.py +++ b/api_tests/preprints/views/test_preprint_contributors_detail.py @@ -194,21 +194,21 @@ def test_preprint_contributor_deleted( # Unauthenticated res = app.get(url_published, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Noncontrib user_two = AuthUserFactory() res = app.get(url_published, auth=user_two.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Write contrib preprint_published.add_contributor(user_two, permissions.WRITE, save=True) res = app.get(url_published, auth=user_two.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Admin contrib res = app.get(url_published, auth=user.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 def test_preprint_contributor_private( self, app, user, preprint_published, url_published): diff --git a/api_tests/preprints/views/test_preprint_contributors_list.py b/api_tests/preprints/views/test_preprint_contributors_list.py index 4572a7749e6..f753245bdd8 100644 --- a/api_tests/preprints/views/test_preprint_contributors_list.py +++ b/api_tests/preprints/views/test_preprint_contributors_list.py @@ -205,20 +205,20 @@ def test_return_preprint_contributors_deleted_preprint( # test_deleted_preprint_contributors_logged_out res = app.get(url_published, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_deleted_preprint_contributor_non_contrib res = app.get(url_published, auth=user_two.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_deleted_preprint_contributors_read_contrib_logged_out preprint_published.add_contributor(user_two, permissions.READ, save=True) res = app.get(url_published, auth=user_two.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # test_deleted_preprint_contributors_admin res = app.get(url_published, auth=user.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 def test_return_preprint_contributors_abandoned_preprint( self, app, user, user_two, preprint_published, url_published): diff --git a/api_tests/preprints/views/test_preprint_detail.py b/api_tests/preprints/views/test_preprint_detail.py index 283f7029c9f..1c08e34bc85 100644 --- a/api_tests/preprints/views/test_preprint_detail.py +++ b/api_tests/preprints/views/test_preprint_detail.py @@ -179,6 +179,26 @@ def test_return_affiliated_institutions(self, app, user, preprint, institution, relationship_link = res.json['data']['relationships']['affiliated_institutions']['links']['self']['href'] assert f'/v2/preprints/{preprint._id}/relationships/institutions/' in relationship_link + def test_spammed_preprint_detail_gone(self, app, preprint, user, url): + preprint.confirm_spam(save=True, train_spam_services=False) + url = f'/{API_BASE}preprints/{preprint._id}/' + res = app.get(url, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested preprint is no longer available.' + assert 'meta' in error + assert error['meta']['flagged_content'] is True + + def test_not_spammed_deleted_preprint_detail_gone(self, app, preprint, user, url): + preprint.deleted = timezone.now() + preprint.save() + res = app.get(url, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested preprint is no longer available.' + assert 'meta' in error + assert not error['meta'].get('flagged_content', False) + @pytest.mark.django_db class TestPreprintDelete: diff --git a/api_tests/preprints/views/test_preprint_detail_reviews.py b/api_tests/preprints/views/test_preprint_detail_reviews.py index 474a858d2b9..66d27329a33 100644 --- a/api_tests/preprints/views/test_preprint_detail_reviews.py +++ b/api_tests/preprints/views/test_preprint_detail_reviews.py @@ -120,7 +120,7 @@ def test_reviews_preprint_is_published_detail( # test_unpublished_invisible_to_public res = app.get(unpublished_url, expect_errors=True) - assert res.status_code == 401 + assert res.status_code == 403 def test_reviews_preprint_initial_detail( self, app, admin, write_contrib, non_contrib, @@ -167,4 +167,4 @@ def test_reviews_preprint_is_public_detail( # test_private_invisible_to_public res = app.get(private_url, expect_errors=True) - assert res.status_code == 401 + assert res.status_code == 403 diff --git a/api_tests/preprints/views/test_preprint_files_list.py b/api_tests/preprints/views/test_preprint_files_list.py index 6b7af924e60..2443f429111 100644 --- a/api_tests/preprints/views/test_preprint_files_list.py +++ b/api_tests/preprints/views/test_preprint_files_list.py @@ -107,20 +107,20 @@ def test_deleted_preprint_files(self): # Unauthenticated res = self.app.get(self.url, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Noncontrib res = self.app.get(self.url, auth=self.user_two.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Write contributor self.preprint.add_contributor(self.user_two, WRITE, save=True) res = self.app.get(self.url, auth=self.user_two.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 # Admin contrib res = self.app.get(self.url, auth=self.user.auth, expect_errors=True) - assert res.status_code == 404 + assert res.status_code == 410 def test_withdrawn_preprint_files(self): self.preprint.date_withdrawn = timezone.now() diff --git a/api_tests/preprints/views/test_preprint_list.py b/api_tests/preprints/views/test_preprint_list.py index df180a3ce69..3208c397893 100644 --- a/api_tests/preprints/views/test_preprint_list.py +++ b/api_tests/preprints/views/test_preprint_list.py @@ -998,6 +998,17 @@ def test_unpublished_visible_to_write_contribs( res = app.get(detail_url, auth=user_write_contrib.auth, expect_errors=True) assert res.json['data']['id'] == preprint_unpublished._id + def test_unpublished_invisible_to_public( + self, app, preprint_unpublished, preprint_published, + list_url, detail_url): + res = app.get(list_url) + assert len(res.json['data']) == 1 + assert preprint_unpublished._id not in [ + d['id'] for d in res.json['data']] + + res = app.get(detail_url, expect_errors=True) + assert res.status_code == 403 + class TestPreprintIsValidList(PreprintIsValidListMixin): diff --git a/api_tests/registrations/views/test_registration_detail.py b/api_tests/registrations/views/test_registration_detail.py index 17649ad7b8d..9d90703ed75 100644 --- a/api_tests/registrations/views/test_registration_detail.py +++ b/api_tests/registrations/views/test_registration_detail.py @@ -233,6 +233,29 @@ def test_registration_detail( expected_url = f'{public_url}relationships/subjects/' assert urlparse(self_url).path == expected_url + def test_spammed_registration_detail_gone(self, app, user, public_registration, private_registration): + for registration in (public_registration, private_registration): + registration.confirm_spam(save=True, train_spam_services=False) + url = f'/{API_BASE}registrations/{registration._id}/' + res = app.get(url, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested registration is no longer available.' + assert 'meta' in error + assert error['meta']['flagged_content'] + + def test_not_spammed_detailed_registration_detail_gone(self, app, user, public_registration, private_registration): + for registration in (public_registration, private_registration): + registration.deleted = timezone.now() + registration.save() + url = f'/{API_BASE}registrations/{registration._id}/' + res = app.get(url, expect_errors=True) + assert res.status_code == 410 + error = res.json['errors'][0] + assert error['detail'] == 'The requested registration is no longer available.' + assert 'meta' in error + assert not error['meta'].get('flagged_content', False) + class TestRegistrationUpdateTestCase: diff --git a/api_tests/registrations/views/test_registration_relationship_institutions.py b/api_tests/registrations/views/test_registration_relationship_institutions.py index 033d59af697..3ee6f8c0486 100644 --- a/api_tests/registrations/views/test_registration_relationship_institutions.py +++ b/api_tests/registrations/views/test_registration_relationship_institutions.py @@ -43,11 +43,11 @@ def resource_factory(self): return RegistrationFactory # test override, write contribs can't update institution - def test_put_not_admin_but_affiliated(self, app, institution_one, node, node_institutions_url): + def test_put_not_admin_but_affiliated_read_permission(self, app, institution_one, node, node_institutions_url): user = AuthUserFactory() user.add_or_update_affiliated_institution(institution_one) user.save() - node.add_contributor(user) + node.add_contributor(user, permissions=permissions.READ) node.save() res = app.put_json_api( @@ -61,7 +61,25 @@ def test_put_not_admin_but_affiliated(self, app, institution_one, node, node_ins assert res.status_code == 403 assert institution_one not in node.affiliated_institutions.all() - # test override, write contribs cannot delete + def test_put_not_admin_but_affiliated_and_write_permission(self, app, institution_one, node, node_institutions_url): + user = AuthUserFactory() + user.add_or_update_affiliated_institution(institution_one) + user.save() + node.add_contributor(user) + node.save() + + res = app.put_json_api( + node_institutions_url, + self.create_payload([institution_one]), + expect_errors=False, + auth=user.auth + ) + + node.reload() + assert res.status_code == 200 + assert institution_one in node.affiliated_institutions.all() + + # test override, write contribs can delete def test_delete_user_is_read_write(self, app, institution_one, node, node_institutions_url): user = AuthUserFactory() user.add_or_update_affiliated_institution(institution_one) @@ -74,10 +92,10 @@ def test_delete_user_is_read_write(self, app, institution_one, node, node_instit node_institutions_url, self.create_payload([institution_one]), auth=user.auth, - expect_errors=True + expect_errors=False ) - assert res.status_code == 403 + assert res.status_code == 204 def test_read_write_contributor_can_add_affiliated_institution( self, app, write_contrib, write_contrib_institution, node, node_institutions_url): @@ -92,10 +110,10 @@ def test_read_write_contributor_can_add_affiliated_institution( ] }, auth=write_contrib.auth, - expect_errors=True + expect_errors=False ) - assert res.status_code == 403 - assert write_contrib_institution not in node.affiliated_institutions.all() + assert res.status_code == 201 + assert write_contrib_institution in node.affiliated_institutions.all() def test_read_write_contributor_can_remove_affiliated_institution( self, app, write_contrib, write_contrib_institution, node, node_institutions_url): @@ -112,10 +130,10 @@ def test_read_write_contributor_can_remove_affiliated_institution( ] }, auth=write_contrib.auth, - expect_errors=True + expect_errors=False ) - assert res.status_code == 403 - assert write_contrib_institution in node.affiliated_institutions.all() + assert res.status_code == 204 + assert write_contrib_institution not in node.affiliated_institutions.all() def test_user_with_institution_and_permissions_through_patch(self, app, user, institution_one, institution_two, node, node_institutions_url): diff --git a/api_tests/users/views/test_user_confirm_external_login.py b/api_tests/users/views/test_user_confirm_external_login.py index bcac3fb1d6c..7a877017a96 100644 --- a/api_tests/users/views/test_user_confirm_external_login.py +++ b/api_tests/users/views/test_user_confirm_external_login.py @@ -34,7 +34,7 @@ def payload(self, user_one): 'attributes': { 'uid': user_one._id, 'token': user_one.get_confirmation_token(user_one.username), - 'destination': 'dashboard', + 'destination': 'my_projects', } } } diff --git a/docker-compose-dist.override.yml b/docker-compose-dist.override.yml index 7a35d24b27b..3a3c2fb8160 100644 --- a/docker-compose-dist.override.yml +++ b/docker-compose-dist.override.yml @@ -29,80 +29,6 @@ # volumes: # - ../modular-file-renderer:/code:cached -# preprints: -# volumes: -# - ../ember-osf-preprints:/code:cached -# -## # Use this for ember-osf linked development: -## - preprints_dist_vol:/code/dist -## - ../ember-osf:/ember-osf -## depends_on: -## - emberosf -## command: -## - /bin/bash -## - -c -## - cd /ember-osf && -## yarn link && -## cd /code && -## (rm -r node_modules || true) && -## yarn --frozen-lockfile && -## yarn link @centerforopenscience/ember-osf && -## (rm -r bower_components || true) && -## ./node_modules/.bin/bower install --allow-root --config.interactive=false && -## yarn start --host 0.0.0.0 --port 4201 --live-reload-port 41954 - -# registries: -# volumes: -# - ../ember-osf-registries:/code:cached -# -## # Use this for ember-osf linked development: -## - registries_dist_vol:/code/dist -## - ../ember-osf:/ember-osf -## depends_on: -## - emberosf -## command: -## - /bin/bash -## - -c -## - cd /ember-osf && -## yarn link && -## cd /code && -## (rm -r node_modules || true) && -## yarn --frozen-lockfile && -## yarn link @centerforopenscience/ember-osf && -## yarn start --host 0.0.0.0 --port 4202 --live-reload-port 41955 - -# reviews: -# volumes: -# - ../ember-osf-reviews:/code:cached -# -## # Use this for ember-osf linked development: -## - reviews_dist_vol:/code/dist -## - ../ember-osf:/ember-osf -## depends_on: -## - emberosf -## command: -## - /bin/bash -## - -c -## - cd /ember-osf && -## yarn link && -## cd /code && -## yarn link @centerforopenscience/ember-osf && -## yarn --frozen-lockfile && -## yarn start --host 0.0.0.0 --port 4203 --live-reload-port 41956 - -# # Use this for ember-osf linked development: -# emberosf: -# build: ../ember-osf -# command: -# - /bin/bash -# - -c -# - (rm -r node_modules || true) && -# yarn --frozen-lockfile --ignore-engines && -# (rm -r bower_components || true) && -# ./node_modules/.bin/bower install --allow-root --config.interactive=false -# volumes: -# - ../ember-osf/:/code:nocopy - # #################### # # RabbitMQ SSL # # Enable this, place the certs in ./ssl, and uncomment the BROKER_USE_SSL dictionary in local.py diff --git a/docker-compose.yml b/docker-compose.yml index f00b589f7e0..9914c24728b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,8 +15,6 @@ volumes: external: false rabbitmq_vol: external: false - ember_osf_web_dist_vol: - external: false preprints_dist_vol: external: false reviews_dist_vol: @@ -255,35 +253,6 @@ services: - postgres stdin_open: true - - ################# - # Ember OSF Web # - ################# - - ember_osf_web: - image: quay.io/centerforopenscience/osf-web:develop-local - command: yarn run start --path dist --host 0.0.0.0 --port 4200 --live-reload-port 41953 - restart: unless-stopped - depends_on: - - api - - web - environment: - # Uncomment below to enable collections on ember - # - COLLECTIONS_ENABLED=true - - BACKEND=local - - SHARE_BASE_URL=http://localhost:8003/ - - SHARE_API_URL=http://localhost:8003/api/v2 - - SHARE_SEARCH_URL=http://localhost:8003/api/v2/search/creativeworks/_search - expose: - - 4200 - - 41953 - ports: - - 4200:4200 - - 41953:41953 - volumes: - - ember_osf_web_dist_vol:/code/dist - stdin_open: true - ############# # Preprints # ############# @@ -523,7 +492,6 @@ services: - osf_requirements_3_12_vol:/usr/local/lib/python3.12/ - osf_bower_components_vol:/code/website/static/vendor/bower_components - osf_node_modules_vol:/code/node_modules - - ember_osf_web_dist_vol:/ember_osf_web - preprints_dist_vol:/preprints - reviews_dist_vol:/reviews stdin_open: true diff --git a/framework/auth/campaigns.py b/framework/auth/campaigns.py index d0be8e1707e..728e14bdc8d 100644 --- a/framework/auth/campaigns.py +++ b/framework/auth/campaigns.py @@ -95,7 +95,7 @@ def get_campaigns(): newest_campaigns.update({ 'agu_conference_2023': { 'system_tag': CampaignSourceTags.AguConference2023.value, - 'redirect_url': furl(DOMAIN).add(path='dashboard/').url, + 'redirect_url': furl(DOMAIN).add(path='my_projects/').url, 'confirmation_email_template': NotificationTypeEnum.USER_CONFIRM_EMAIL, # added as a placeholder as removed NotificationType 'login_type': 'native', } @@ -104,7 +104,7 @@ def get_campaigns(): newest_campaigns.update({ 'agu_conference': { 'system_tag': CampaignSourceTags.AguConference.value, - 'redirect_url': furl(DOMAIN).add(path='dashboard/').url, + 'redirect_url': furl(DOMAIN).add(path='my_projects/').url, 'confirmation_email_template': NotificationTypeEnum.USER_CAMPAIGN_CONFIRM_EMAIL_AGU_CONFERENCE, 'login_type': 'native', } diff --git a/framework/auth/views.py b/framework/auth/views.py index aefb1b4f0e8..f7450c42a47 100644 --- a/framework/auth/views.py +++ b/framework/auth/views.py @@ -35,8 +35,6 @@ from osf.models.tag import Tag from osf.utils.requests import check_select_for_update from website.util.metrics import CampaignClaimedTags, CampaignSourceTags -from website.ember_osf_web.decorators import ember_flag_is_active -from osf import features @block_bing_preview @@ -85,8 +83,8 @@ def _reset_password_get(auth, uid=None, token=None, institutional=False): } raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data=error_data) - # override routes.py login_url to redirect to dashboard - service_url = web_url_for('dashboard', _absolute=True) + # override routes.py login_url to redirect to my-projects + service_url = web_url_for('my_projects', _absolute=True) return { 'uid': user_obj._id, @@ -176,9 +174,9 @@ def forgot_password_get(auth): if auth.logged_in: return auth_logout(redirect_url=request.url) - #overriding the routes.py sign in url to redirect to the dashboard after login + #overriding the routes.py sign in url to redirect to the my-projects after login context = {} - context['login_url'] = web_url_for('dashboard', _absolute=True) + context['login_url'] = web_url_for('my_projects', _absolute=True) return context @@ -326,7 +324,7 @@ def login_and_register_handler(auth, login=True, campaign=None, next_url=None, l # unlike other campaigns, institution login serves as an alternative for authentication if campaign == 'institution': if next_url is None: - next_url = web_url_for('dashboard', _absolute=True) + next_url = web_url_for('my_projects', _absolute=True) data['status_code'] = http_status.HTTP_302_FOUND if auth.logged_in: data['next_url'] = next_url @@ -393,7 +391,7 @@ def login_and_register_handler(auth, login=True, campaign=None, next_url=None, l # `/login/` or `/register/` without any parameter if auth.logged_in: data['status_code'] = http_status.HTTP_302_FOUND - data['next_url'] = web_url_for('dashboard', _absolute=True) + data['next_url'] = web_url_for('my_projects', _absolute=True) return data @@ -410,7 +408,7 @@ def auth_login(auth): if campaign and logged out, go to campaign register page (with next_url if presents) if next_url and logged in, go to next url if next_url and logged out, go to cas login page with current request url as service parameter - if none, go to `/dashboard` which is decorated by `@must_be_logged_in` + if none, go to `/my-projects` which is decorated by `@must_be_logged_in` :param auth: the auth context :return: redirects @@ -425,7 +423,6 @@ def auth_login(auth): @collect_auth -@ember_flag_is_active(features.EMBER_AUTH_REGISTER) def auth_register(auth): """ View for OSF register. Land on the register page, redirect or go to `auth_logout` @@ -438,7 +435,7 @@ def auth_register(auth): if next_url and logged in, go to next url if next_url and logged out, go to cas login page with current request url as service parameter if next_url and logout flag, log user out first and then go to the next_url - if none, go to `/dashboard` which is decorated by `@must_be_logged_in` + if none, go to `/my-projects` which is decorated by `@must_be_logged_in` :param auth: the auth context :return: land, redirect or `auth_logout` @@ -548,7 +545,7 @@ def auth_email_logout(token, user): When a user is adding an email or merging an account, add the email to the user and log them out. """ - redirect_url = cas.get_logout_url(service_url=cas.get_login_url(service_url=web_url_for('index', _absolute=True))) + redirect_url = cas.get_logout_url(service_url=cas.get_login_url(service_url=web_url_for('auth_login', _absolute=True))) try: unconfirmed_email = user.get_unconfirmed_email_for_token(token) except InvalidTokenError: @@ -617,7 +614,7 @@ def external_login_confirm_email_get(auth, uid, token): return redirect(campaign_url) if new: status.push_status_message(language.WELCOME_MESSAGE, kind='default', jumbotron=True, trust=True, id='welcome_message') - return redirect(web_url_for('dashboard')) + return redirect(web_url_for('my_projects')) # token is invalid if token not in user.email_verifications: @@ -716,7 +713,7 @@ def confirm_email_get(token, auth=None, **kwargs): status.push_status_message(language.WELCOME_MESSAGE, kind='default', jumbotron=True, trust=True, id='welcome_message') if token in auth.user.email_verifications: status.push_status_message(language.CONFIRM_ALTERNATE_EMAIL_ERROR, kind='danger', trust=True, id='alternate_email_error') - return redirect(web_url_for('index')) + return redirect(web_url_for('my_projects')) status.push_status_message(language.MERGE_COMPLETE, kind='success', trust=False) return redirect(web_url_for('user_account')) @@ -998,7 +995,7 @@ def resend_confirmation_post(auth): try: send_confirm_email(user, clean_email, renew=True) except KeyError: - # already confirmed, redirect to dashboard + # already confirmed, redirect to my-projects status_message = f'This email {clean_email} has already been confirmed.' kind = 'warning' user.email_last_sent = timezone.now() @@ -1058,7 +1055,7 @@ def external_login_email_post(): service_url = session.get('service_url', None) # TODO: @cslzchen use user tags instead of destination - destination = 'dashboard' + destination = 'my_projects' for campaign in campaigns.get_campaigns(): if campaign != 'institution': # Handle different url encoding schemes between `furl` and `urlparse/urllib`. diff --git a/framework/sessions/__init__.py b/framework/sessions/__init__.py index 21dc850cb53..5891cb6d69f 100644 --- a/framework/sessions/__init__.py +++ b/framework/sessions/__init__.py @@ -216,7 +216,7 @@ def before_request(): try: user_session = flask_get_session_from_cookie(cookie) except InvalidCookieOrSessionError: - response = redirect(web_url_for('index')) + response = redirect(web_url_for('auth_login')) response.delete_cookie(settings.COOKIE_NAME, domain=settings.OSF_COOKIE_DOMAIN) return response # Case 1: anonymous session that is used for first time external (e.g. ORCiD) login only diff --git a/osf/external/spam/tasks.py b/osf/external/spam/tasks.py index 9c2a348cdcd..4cb4c7784b5 100644 --- a/osf/external/spam/tasks.py +++ b/osf/external/spam/tasks.py @@ -103,6 +103,29 @@ def check_resource_with_spam_services(resource, content, author, author_email, r """ Return statements used only for debugging and recording keeping """ + from osf.models import OSFUser, AbstractNode, Preprint + + def set_found_spam_info(resource, client, details): + if not resource.spam_data.get('who_flagged'): + resource.spam_data['who_flagged'] = client.NAME + elif resource.spam_data['who_flagged'] != client.NAME: + resource.spam_data['who_flagged'] = 'both' + + if client.NAME == 'akismet': + resource.spam_pro_tip = details + if client.NAME == 'oopspam': + resource.spam_data['oopspam_data'] = details + + def set_collected_info(resource): + resource.spam_data['headers'] = { + 'Remote-Addr': request_kwargs.get('remote_addr'), + 'User-Agent': request_kwargs.get('user_agent'), + 'Referer': request_kwargs.get('referer'), + } + resource.spam_data['content'] = content + resource.spam_data['author'] = author + resource.spam_data['author_email'] = author_email + any_is_spam = False kwargs = dict( @@ -121,30 +144,57 @@ def check_resource_with_spam_services(resource, content, author, author_email, r if settings.OOPSPAM_ENABLED: spam_clients.append(OOPSpamClient()) + if isinstance(resource, OSFUser): + creator = resource + else: + creator = OSFUser.objects.get(username=author_email) + + nodes_to_flag = creator.nodes.filter(is_public=True, is_deleted=False) + preprints_to_flag = creator.preprints.filter(is_public=True, deleted__isnull=True) + for client in spam_clients: is_spam, details = client.check_content(**kwargs) - if is_spam: - any_is_spam = True - if not resource.spam_data.get('who_flagged'): - resource.spam_data['who_flagged'] = client.NAME - elif resource.spam_data['who_flagged'] != client.NAME: - resource.spam_data['who_flagged'] = 'both' - - if client.NAME == 'akismet': - resource.spam_pro_tip = details - if client.NAME == 'oopspam': - resource.spam_data['oopspam_data'] = details - - if any_is_spam: - resource.spam_data['headers'] = { - 'Remote-Addr': request_kwargs.get('remote_addr'), - 'User-Agent': request_kwargs.get('user_agent'), - 'Referer': request_kwargs.get('referer'), - } - resource.spam_data['content'] = content - resource.spam_data['author'] = author - resource.spam_data['author_email'] = author_email - resource.flag_spam() + if not is_spam: + continue + + any_is_spam = True + + set_found_spam_info(resource, client, details) + if not isinstance(resource, OSFUser) and not creator.is_hammy: + set_found_spam_info(creator, client, details) + + for node in nodes_to_flag: + set_found_spam_info(node, client, details) + + for preprint in preprints_to_flag: + set_found_spam_info(preprint, client, details) + + if not any_is_spam: + return any_is_spam + + sentry.log_message( + f"Spam data detected by akismet/oops for {resource._id}:" + f"{resource.spam_pro_tip or resource.spam_data.get('oopspam_data')}" + ) + + set_collected_info(resource) + resource.flag_spam(skip_user_suspension=True) + + # set spam_data but don't flag the creator because it'll happen at the end of check_resource_for_spam_postcommit + if not isinstance(resource, OSFUser) and not creator.is_hammy: + set_collected_info(creator) + creator.save() + + for node in nodes_to_flag: + set_collected_info(node) + node.flag_spam(skip_user_suspension=True) + + for preprint in preprints_to_flag: + set_collected_info(preprint) + preprint.flag_spam(skip_user_suspension=True) + + AbstractNode.objects.bulk_update(nodes_to_flag, ['spam_status', 'spam_data', 'spam_pro_tip'], batch_size=100) + Preprint.objects.bulk_update(preprints_to_flag, ['spam_status', 'spam_data', 'spam_pro_tip'], batch_size=100) return any_is_spam @@ -158,6 +208,10 @@ def check_resource_for_spam_postcommit(guid, content, author, author_email, requ if not resource: return f'{guid} not found' + if isinstance(resource, OSFUser) and resource.is_hammy: + sentry.log_message(f"User {guid} is not checked for spam because of ham status") + return + spammy_domains = _check_resource_for_domains(resource, content) if spammy_domains: sentry.log_message(f"Spammy domains detected for {guid}: {spammy_domains}") @@ -181,9 +235,9 @@ def check_resource_for_spam_postcommit(guid, content, author, author_email, requ resource.save() - if hasattr(resource, 'check_spam_user'): - user = OSFUser.objects.get(username=author_email) - resource.check_spam_user(user) + user = OSFUser.objects.get(username=author_email) + if hasattr(resource, 'check_spam_user') and not user.is_hammy: + resource.check_spam_user(user, domains=list(spammy_domains)) @celery_app.task(ignore_results=False, max_retries=5, default_retry_delay=60) diff --git a/osf/features.yaml b/osf/features.yaml index 00a792b4933..cce490a25a4 100644 --- a/osf/features.yaml +++ b/osf/features.yaml @@ -9,7 +9,7 @@ # 3. Use the admin app to enable/disable the flag/switch at your convenience # 4. When feature is complete add the activity status (active or everyone) to the value it will have in production until # the old flipping code can be removed. -# 5. When a flag name is no longer referenced anywhere in this repo or in the Ember app remove it from this list. +# 5. When a flag name is no longer referenced anywhere in this repo remove it from this list. flags: - flag_name: MANUAL_DOI_AND_GUID @@ -21,18 +21,7 @@ flags: - flag_name: ENABLE_GV name: gravy_waffle note: This is used to enable GravyValet, the system responsible for addons, this will remove the files widget on the - project overview page. Will be used with EMBER_USER_SETTINGS_ADDONS and EMBER_NODE_SETTINGS_ADDONS to flip all - UI elements to the new addons system. - everyone: true - - - flag_name: EMBER_FILE_PROJECT_DETAIL - name: ember_file_project_detail_page - note: This is part of the upcoming files page redesign - everyone: true - - - flag_name: EMBER_PROJECT_FILES - name: ember_project_files_page - note: This is part of the upcoming files page redesign + project overview page. everyone: true - flag_name: STORAGE_USAGE @@ -60,136 +49,6 @@ flags: note: Indicates whether EGAP admins have special access to custom schemas everyone: true - - flag_name: EMBER_AUTH_REGISTER - name: ember_auth_register - note: This indicates whether this view is routed for OSF register, redirect or go to `auth_logout` - everyone: true - - - flag_name: EMBER_PROJECT_DETAIL - name: ember_project_detail_page - note: This flag controls whether the project overview page is routed to the ember app - everyone: false - - - flag_name: EMBER_CREATE_DRAFT_REGISTRATION - name: ember_create_draft_registration_page - note: This flag controls whether POST requests to /project//registrations/ and - /project//node//registrations/ are routed to the ember app - everyone: false - - - flag_name: EMBER_MEETING_DETAIL - name: ember_meeting_detail_page - note: This flag controls whether the `conference_results` view routes to the Ember app - everyone: true - - - flag_name: EMBER_MY_PROJECTS - name: ember_my_projects_page - note: This flag controls whether the `My Projects Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_PROJECT_CONTRIBUTORS - name: ember_project_contributors_page - note: This flag controls whether the `Node Contributor Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_PROJECT_SETTINGS - name: ember_project_settings_page - note: This flag controls whether the `Node Settings Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_PROJECT_WIKI - name: ember_project_wiki_page - note: This flag controls whether the `Project Wiki Home Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_REGISTRATION_FORM_DETAIL - name: ember_registration_form_detail_page - note: This flag controls whether the `Node Register Template Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_SEARCH_PAGE - name: ember_search_page - note: This flag controls whether the `Search Page` view routes to the Ember app - everyone: true - - - flag_name: EMBER_USER_PROFILE - name: ember_user_profile_page - note: This flag controls whether the `User Profile Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_USER_SETTINGS - name: ember_user_settings_page - note: This flag controls whether the `User Settings Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_USER_SETTINGS_NOTIFICATIONS - name: ember_user_settings_notifications_page - note: This flag controls whether the `User Notifications Page` view routes to the Ember app - everyone: false - - - flag_name: EMBER_MEETINGS - name: ember_meetings_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_EDIT_DRAFT_REGISTRATION - name: ember_edit_draft_registration_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_FILE_REGISTRATION_DETAIL - name: ember_file_registration_detail_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_REGISTRATION_FILES - name: ember_registration_files_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_REGISTRIES_DETAIL_PAGE - name: ember_registries_detail_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_USER_SETTINGS_ACCOUNTS - name: ember_user_settings_account_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_USER_SETTINGS_APPS - name: ember_user_settings_apps_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_USER_SETTINGS_TOKENS - name: ember_user_settings_tokens_page - note: This is complete and should be permanently on. - everyone: true - - - flag_name: EMBER_AB_TESTING_HOME_PAGE_VERSION_B - name: ab_testing_home_page_version_b - note: This is no longer used. - - - flag_name: EMBER_AB_TESTING_HOME_PAGE_HERO_TEXT_VERSION_B - name: ab_testing_home_page_hero_text_version_b - note: This is no longer used. - everyone: true - - - flag_name: EMBER_PROJECT_ANALYTICS - name: ember_project_analytics_page - note: This is no longer used. - everyone: false - - - flag_name: EMBER_PROJECT_FORKS - name: ember_project_forks_page - note: This is no longer used. - everyone: false - - - flag_name: EMBER_PROJECT_REGISTRATIONS - name: ember_project_registrations_page - note: This is no longer used. - everyone: false - - flag_name: ENABLE_CHRONOS name: enable_chronos note: This is not used diff --git a/osf/management/commands/change_node_region.py b/osf/management/commands/change_node_region.py index b0c97630182..e66cc961b22 100644 --- a/osf/management/commands/change_node_region.py +++ b/osf/management/commands/change_node_region.py @@ -39,11 +39,14 @@ def _update_blocks(file_block_map, original_id, cloned_id): block.save() def _update_schema_meta(node): - logger.info('Updating legacy schema information...') - node.registration_responses = node.schema_responses.latest('-created').all_responses - node.registered_meta[node.registration_schema._id] = node.expand_registration_responses() - node.save() - logger.info('Updated legacy schema information.') + try: + logger.info('Updating legacy schema information...') + node.registration_responses = node.schema_responses.latest('-created').all_responses + node.registered_meta[node.registration_schema._id] = node.expand_registration_responses() + node.save() + logger.info('Updated legacy schema information.') + except Exception: + logger.error('There is no data in schema responses to update legacy schema information.') def _copy_and_clone_versions(original_file, cloned_file, src_bucket, dest_bucket, dest_bucket_name, dest_region): for v in original_file.versions.order_by('identifier').all(): diff --git a/osf/management/commands/metrics_backfill_pageviews.py b/osf/management/commands/metrics_backfill_pageviews.py index 4a3cc729d0d..13898037923 100644 --- a/osf/management/commands/metrics_backfill_pageviews.py +++ b/osf/management/commands/metrics_backfill_pageviews.py @@ -27,12 +27,12 @@ def main(source, dry_run=False, resume_from=None): # page.info.protocol + page.info.domain => _source.platform_iri # "http://localhost:5000/", # visitor.session => _source.session_id # "fcae918a3b6a19641bd0087f84083f0d57982d8c93ab821c405561d1b5c7b305", # user.id => _source.user_is_authenticated # true, - # page.url => _source.pageview_info.page_url # "http://localhost:5000/myprojects/", + # page.url => _source.pageview_info.page_url # "http://localhost:5000/my-projects/", # page.title => _source.pageview_info.page_title # "OSF | My Projects", # referrer.url => _source.pageview_info.referer_url # "http://localhost:5000/csab4/analytics", # page.meta.routeName => _source.pageview_info.route_name # "OsfWebRenderer.my_projects", # time.utc.hour_of_day => _source.pageview_info.hour_of_day # 4, - # page.info.path => _source.pageview_info.page_path # "/myprojects", + # page.info.path => _source.pageview_info.page_path # "/my-projects", # referrer.info.domain => _source.pageview_info.referer_domain # "localhost:5000" # page.meta.public => _source.item_public # true, # node.id => _source.item_guid # "ry7dn", @@ -85,7 +85,7 @@ def populate_action_labels(something_wonderful, row): if row['page.info.path']: path_parts = row['page.info.path'].split('/') - if len(path_parts) == 1 and path_parts[0] not in ('myprojects', 'goodbye', 'login'): + if len(path_parts) == 1 and path_parts[0] not in ('my-projects', 'goodbye', 'login'): labels.append('view') elif path_parts[1] in ('wiki'): labels.append('view') diff --git a/osf/management/commands/process_manual_restart_approvals.py b/osf/management/commands/process_manual_restart_approvals.py new file mode 100644 index 00000000000..e708320357f --- /dev/null +++ b/osf/management/commands/process_manual_restart_approvals.py @@ -0,0 +1,145 @@ +import logging +from datetime import timedelta +from django.core.management.base import BaseCommand +from django.utils import timezone +from osf.models import Registration +from osf.models.admin_log_entry import AdminLogEntry, MANUAL_ARCHIVE_RESTART +from website import settings +from scripts.approve_registrations import approve_past_pendings + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = 'Process registrations that were manually restarted and may need approval' + + def add_arguments(self, parser): + parser.add_argument( + '--dry-run', + action='store_true', + help='Show what would be done without actually doing it', + ) + parser.add_argument( + '--hours-back', + type=int, + default=72, + help='How many hours back to look for manual restarts (default: 72)', + ) + parser.add_argument( + '--registration-id', + type=str, + help='Process a specific registration ID only', + ) + + def handle(self, *args, **options): + dry_run = options['dry_run'] + hours_back = options['hours_back'] + specific_registration = options.get('registration_id') + + if dry_run: + self.stdout.write(self.style.WARNING('Running in DRY RUN mode - no changes will be made')) + + since = timezone.now() - timedelta(hours=hours_back) + + query = AdminLogEntry.objects.filter( + action_flag=MANUAL_ARCHIVE_RESTART, + action_time__gte=since + ) + + if specific_registration: + try: + reg = Registration.objects.get(_id=specific_registration) + query = query.filter(object_id=reg.pk) + self.stdout.write(f"Processing specific registration: {specific_registration}") + except Registration.DoesNotExist: + self.stdout.write(self.style.ERROR(f"Registration {specific_registration} not found")) + return + + manual_restart_logs = query.values_list('object_id', flat=True).distinct() + + registrations_to_check = Registration.objects.filter( + pk__in=manual_restart_logs, + ) + + self.stdout.write(f"Found {registrations_to_check.count()} manually restarted registrations to check") + + approvals_ready = [] + skipped_registrations = [] + + for registration in registrations_to_check: + status = self.should_auto_approve(registration) + + if status == 'ready': + approval = registration.registration_approval + if approval: + approvals_ready.append(approval) + self.stdout.write( + self.style.SUCCESS(f"✓ Queuing registration {registration._id} for approval") + ) + else: + skipped_registrations.append((registration._id, status)) + self.stdout.write( + self.style.WARNING(f"⚠ Skipping registration {registration._id}: {status}") + ) + + if approvals_ready: + if dry_run: + self.stdout.write( + self.style.WARNING(f"DRY RUN: Would approve {len(approvals_ready)} registrations") + ) + else: + try: + approve_past_pendings(approvals_ready, dry_run=False) + self.stdout.write( + self.style.SUCCESS(f"✓ Successfully approved {len(approvals_ready)} manually restarted registrations") + ) + except Exception as e: + self.stdout.write( + self.style.ERROR(f"✗ Error approving registrations: {e}") + ) + else: + self.stdout.write('No registrations ready for approval') + + self.stdout.write(f"Total checked: {registrations_to_check.count()}") + self.stdout.write(f"Ready for approval: {len(approvals_ready)}") + self.stdout.write(f"Skipped: {len(skipped_registrations)}") + + if skipped_registrations: + self.stdout.write('\nSkipped registrations:') + for reg_id, reason in skipped_registrations: + self.stdout.write(f" - {reg_id}: {reason}") + + def should_auto_approve(self, registration): + if registration.is_public: + return 'already public' + + if registration.is_registration_approved: + return 'already approved' + + if registration.archiving: + return 'still archiving' + + archive_job = registration.archive_job + if archive_job and hasattr(archive_job, 'status'): + if archive_job.status not in ['SUCCESS', None]: + return f'archive status: {archive_job.status}' + + approval = registration.registration_approval + if not approval: + return 'no approval object' + + if approval.is_approved: + return 'approval already approved' + + if approval.is_rejected: + return 'approval was rejected' + + time_since_initiation = timezone.now() - approval.initiation_date + if time_since_initiation < settings.REGISTRATION_APPROVAL_TIME: + remaining = settings.REGISTRATION_APPROVAL_TIME - time_since_initiation + return f'not ready yet ({remaining} remaining)' + + if registration.is_stuck_registration: + return 'registration still stuck' + + return 'ready' diff --git a/osf/management/commands/reindex_versioned_preprints.py b/osf/management/commands/reindex_versioned_preprints.py index b48e53487e6..c588859585a 100644 --- a/osf/management/commands/reindex_versioned_preprints.py +++ b/osf/management/commands/reindex_versioned_preprints.py @@ -38,12 +38,6 @@ def reindex_versioned_preprints(dry_run=False, batch_size=100, provider_id=None, else: try: preprint.update_search() - if processed % 10 == 0: - logger.info( - f'Re-indexed preprint {preprint._id} ' - f'(version {preprint.versioned_guids.first().version if preprint.versioned_guids.exists() else "N/A"}) ' - f'[{processed}/{total_count}]' - ) except Exception as e: logger.error(f'Failed to re-index preprint {preprint._id}: {e}') diff --git a/osf/metadata/osf_gathering.py b/osf/metadata/osf_gathering.py index dfa74612bd0..240e5c96561 100644 --- a/osf/metadata/osf_gathering.py +++ b/osf/metadata/osf_gathering.py @@ -422,6 +422,8 @@ def gather_flexible_types(focus): def gather_created(focus): if focus.rdftype == OSF.Registration: yield (DCTERMS.created, getattr(focus.dbmodel, 'registered_date', None)) + elif focus.rdftype == OSF.Preprint: + yield (DCTERMS.created, focus.dbmodel.date_created_first_version) else: yield (DCTERMS.created, getattr(focus.dbmodel, 'created', None)) diff --git a/osf/models/admin_log_entry.py b/osf/models/admin_log_entry.py index 99f4de940f5..1597f514375 100644 --- a/osf/models/admin_log_entry.py +++ b/osf/models/admin_log_entry.py @@ -37,6 +37,8 @@ DOI_CREATION_FAILED = 80 DOI_UPDATE_FAILED = 81 +MANUAL_ARCHIVE_RESTART = 90 + def update_admin_log(user_id, object_id, object_repr, message, action_flag=UNKNOWN): AdminLogEntry.objects.log_action( user_id=user_id, diff --git a/osf/models/archive.py b/osf/models/archive.py index 052d918a99c..9e622764ca7 100644 --- a/osf/models/archive.py +++ b/osf/models/archive.py @@ -146,7 +146,7 @@ def _set_target(self, addon_short_name): def set_targets(self): addons = [] - for addon in [self.src_node.get_addon(name) + for addon in [self.src_node.get_addon(name, cached=False) for name in settings.ADDONS_ARCHIVABLE if settings.ADDONS_ARCHIVABLE[name] != 'none']: if not addon or not isinstance(addon, BaseStorageAddon) or not addon.complete: diff --git a/osf/models/brand.py b/osf/models/brand.py index 5a857f5f3b1..54d78252f96 100644 --- a/osf/models/brand.py +++ b/osf/models/brand.py @@ -25,5 +25,22 @@ class Meta: secondary_color = models.CharField(max_length=7) background_color = models.CharField(max_length=7, blank=True, null=True) + @property + def name_lower(self): + return self.name.lower() if self.name else '' + + def get_provider_types(self): + unique_types = self.providers.values_list('type', flat=True).distinct() + results = [] + # cast osf.collectionprovider, osf.registrationprovider, osf.preprintprovider to more readable UI format + for unique_type in unique_types: + if 'registration' in unique_type: + results.append('Registry') + elif 'collection' in unique_type: + results.append('Collection') + elif 'preprint' in unique_type: + results.append('Preprint') + return ', '.join(results) + def __str__(self): return f'{self.name} ({self.id})' diff --git a/osf/models/mixins.py b/osf/models/mixins.py index c115a23610c..689ffe817df 100644 --- a/osf/models/mixins.py +++ b/osf/models/mixins.py @@ -563,14 +563,14 @@ def get_or_add_addon(self, name, *args, **kwargs): return addon return self.add_addon(name, *args, **kwargs) - def get_addon(self, name, is_deleted=False, auth=None): + def get_addon(self, name, is_deleted=False, auth=None, cached=True): # Avoid test-breakages by avoiding early access to the request context if name not in self.OSF_HOSTED_ADDONS: request, user_id = get_request_and_user_id() if not user_id and auth and auth.user: user_id = auth.user._id if flag_is_active(request, features.ENABLE_GV): - return self._get_addon_from_gv(gv_pk=name, requesting_user_id=user_id, auth=auth) + return self._get_addon_from_gv(gv_pk=name, requesting_user_id=user_id, auth=auth, cached=cached) try: settings_model = self._settings_model(name) @@ -1457,7 +1457,7 @@ def add_contributor( # Add default contributor permissions permissions = permissions or self.DEFAULT_CONTRIBUTOR_PERMISSIONS - self.add_permission(contrib_to_add, permissions, save=True) + self.add_permission(contrib_to_add, permissions, save=False) if make_curator: contributor_obj.is_curator = True contributor_obj.save() @@ -1514,6 +1514,7 @@ def add_contributors( :param log: Add log to self :param save: Save after adding contributor """ + users = [] for contrib in contributors: self.add_contributor( contributor=contrib['user'], @@ -1524,6 +1525,7 @@ def add_contributors( save=False, notification_type=notification_type ) + users.append(contrib['user']) if log and contributors: params = self.log_params params['contributors'] = [ @@ -1539,6 +1541,8 @@ def add_contributors( if save: self.save() + return self.contributor_set.filter(user__in=users) + def add_unregistered_contributor( self, fullname, @@ -1547,7 +1551,9 @@ def add_unregistered_contributor( notification_type=False, visible=True, permissions=None, - existing_user=None + existing_user=None, + save=True, + log=True, ): """Add a non-registered contributor to the project. @@ -1612,25 +1618,31 @@ def add_unregistered_contributor( auth=auth, visible=visible, notification_type=notification_type, - log=True, - save=False + log=log, + save=False, ) self._add_related_source_tags(contributor) - self.save() + if save: + self.save() return contributor - def add_contributor_registered_or_not(self, - auth, - user_id=None, - full_name=None, - email=None, - notification_type=False, - permissions=None, - bibliographic=True, - index=None): + def add_contributor_registered_or_not( + self, + auth, + user_id=None, + full_name=None, + email=None, + notification_type=False, + permissions=None, + bibliographic=True, + index=None, + user=None, + save=True, + log=True, + ): OSFUser = apps.get_model('osf.OSFUser') if user_id: - contributor = OSFUser.load(user_id) + contributor = user or OSFUser.load(user_id) if not contributor: raise ValueError(f'User with id {user_id} was not found.') @@ -1644,7 +1656,8 @@ def add_contributor_registered_or_not(self, visible=bibliographic, permissions=permissions, notification_type=notification_type, - save=True + save=save, + log=log ) else: if not full_name: @@ -1660,6 +1673,8 @@ def add_contributor_registered_or_not(self, permissions=permissions, visible=bibliographic, existing_user=contributor, + save=save, + log=log, ) else: @@ -1674,7 +1689,8 @@ def add_contributor_registered_or_not(self, visible=bibliographic, notification_type=notification_type, permissions=permissions, - save=True + save=save, + log=log, ) else: contributor = self.add_unregistered_contributor( @@ -1683,18 +1699,69 @@ def add_contributor_registered_or_not(self, auth=auth, notification_type=notification_type, permissions=permissions, - visible=bibliographic + visible=bibliographic, + save=save, + log=log, ) auth.user.email_last_sent = timezone.now() auth.user.save() if index is not None: - self.move_contributor(contributor=contributor, index=index, auth=auth, save=True) + self.move_contributor(contributor=contributor, index=index, auth=auth, save=save) contributor_obj = self.contributor_set.get(user=contributor) return contributor_obj + def add_contributors_registered_or_not(self, contributors, auth=None, log=True, save=False): + """Add multiple contributors using the unified registered-or-not path. + + Each item should be a dictionary with keys compatible with + `add_contributor_registered_or_not`, e.g.: + { + 'user_id': '', + 'user': '' or None, + 'email': '' or None, + 'full_name': '' or None, + 'notification_type': '' or None, + 'permissions': , + 'bibliographic': , + 'index': , + } + """ + results = [] + + for item in contributors: + contributor_obj = self.add_contributor_registered_or_not( + auth=auth, + user_id=item.get('user_id'), + user=item.get('user'), + full_name=item.get('full_name'), + email=item.get('email'), + notification_type=item.get('notification_type'), + permissions=item.get('permissions'), + bibliographic=item.get('bibliographic', True), + index=item.get('index'), + save=False, + log=False, + ) + results.append(contributor_obj) + + if log and results: + params = self.log_params + params['contributors'] = [c.user._id for c in results] + self.add_log( + action=self.log_class.CONTRIB_ADDED, + params=params, + auth=auth, + save=False, + ) + + if save: + self.save() + + return results + def replace_contributor(self, old, new): """ Replacing unregistered contributor with a verified user @@ -2298,28 +2365,32 @@ def check_spam(self, user, saved_fields, request_headers): request_headers, ) - def check_spam_user(self, user): + def check_spam_user(self, user, domains=None): if ( - settings.SPAM_ACCOUNT_SUSPENSION_ENABLED - and (timezone.now() - user.date_confirmed) <= settings.SPAM_ACCOUNT_SUSPENSION_THRESHOLD + settings.SPAM_ACCOUNT_SUSPENSION_ENABLED + and (timezone.now() - user.date_confirmed) <= settings.SPAM_ACCOUNT_SUSPENSION_THRESHOLD ) or ( - settings.SPAM_AUTOBAN_IP_BLOCK and self.spam_data.get('oopspam_data', None) - and self.spam_data['oopspam_data']['Details']['isIPBlocked'] + settings.SPAM_AUTOBAN_IP_BLOCK and self.spam_data.get('oopspam_data', None) + and self.spam_data['oopspam_data']['Details']['isIPBlocked'] ): - self.suspend_spam_user(user) + self.suspend_spam_user(user, domains=domains) - def suspend_spam_user(self, user): + def suspend_spam_user(self, user, domains=None, self_spam=False): """ This suspends a users account and makes all there resources private, key word here is SUSPENDS this should not delete the account or any info associated with it. It should not be assumed the account is spam and it should not be used to train spam detecting services. + + self_spam - defines if this object must be spammed. When spam is found by akismet or oopsystem, object becomes flagged + and we don't need to spam it but for some cases we want to manually call this method with self spamming. """ + domains = domains or [] if user.is_hammy: return False - self.confirm_spam(save=True, train_spam_services=False) + + self.flag_spam(skip_user_suspension=True) # Suspend the flagged user for spam. - user.flag_spam() if not user.is_disabled: user.deactivate_account() NotificationTypeEnum.USER_SPAM_BANNED.instance.emit( @@ -2329,19 +2400,21 @@ def suspend_spam_user(self, user): 'osf_support_email': settings.OSF_SUPPORT_EMAIL, } ) + + user.confirm_spam(domains=domains or [], save=False, skip_resources_spam=True) user.save() # Make public nodes private from this contributor for node in user.all_nodes: - if self._id != node._id and len(node.contributors) == 1 and node.is_public: - node.confirm_spam(save=True, train_spam_services=False) + if (self._id != node._id or self_spam) and len(node.contributors) == 1 and node.is_public: + node.confirm_spam(save=True, domains=domains, train_spam_services=False) # Make preprints private from this contributor for preprint in user.preprints.all(): - if self._id != preprint._id and len(preprint.contributors) == 1 and preprint.is_public: - preprint.confirm_spam(save=True, train_spam_services=False) + if (self._id != preprint._id or self_spam) and len(preprint.contributors) == 1 and preprint.is_public: + preprint.confirm_spam(save=True, domains=domains, train_spam_services=False) - def flag_spam(self): + def flag_spam(self, skip_user_suspension=False): """ Overrides SpamMixin#flag_spam. """ super().flag_spam() @@ -2357,7 +2430,7 @@ def flag_spam(self): ) log.save() - if settings.SPAM_THROTTLE_AUTOBAN: + if settings.SPAM_THROTTLE_AUTOBAN and not skip_user_suspension: creator = self.creator yesterday = timezone.now() - timezone.timedelta(days=1) node_spam_count = creator.all_nodes.filter(spam_status__in=[SpamStatus.FLAGGED, SpamStatus.SPAM], diff --git a/osf/models/node.py b/osf/models/node.py index fa08e77eee8..083ccd6edfa 100644 --- a/osf/models/node.py +++ b/osf/models/node.py @@ -2505,21 +2505,28 @@ def _remove_from_associated_collections(self, auth=None, force=False): force=True ) - def _get_addon_from_gv(self, gv_pk, requesting_user_id, auth=None): + def _get_addons_from_gv_without_caching(self, gv_pk, requesting_user_id, auth=None): + requesting_user = OSFUser.load(requesting_user_id) + services = gv_translations.get_external_services(requesting_user) + for service in services: + if service.short_name == gv_pk: + break + else: + return [] + + return self._get_addons_from_gv(requesting_user_id, service.type, auth=auth) + + def _get_addon_from_gv(self, gv_pk, requesting_user_id, auth=None, cached=True): request = get_current_request() # This is to avoid making multiple requests to GV # within the lifespan of one request on the OSF side - try: - gv_addons = request.gv_addons - except AttributeError: - requesting_user = OSFUser.load(requesting_user_id) - services = gv_translations.get_external_services(requesting_user) - for service in services: - if service.short_name == gv_pk: - break - else: - return None - gv_addons = request.gv_addons = self._get_addons_from_gv(requesting_user_id, service.type, auth=auth) + if cached: + try: + gv_addons = request.gv_addons + except AttributeError: + gv_addons = request.gv_addons = self._get_addons_from_gv_without_caching(gv_pk, requesting_user_id, auth=auth) + else: + gv_addons = self._get_addons_from_gv_without_caching(gv_pk, requesting_user_id, auth=auth) for item in gv_addons: if item.short_name == gv_pk: diff --git a/osf/models/spam.py b/osf/models/spam.py index d2f5946533c..43e862d97db 100644 --- a/osf/models/spam.py +++ b/osf/models/spam.py @@ -68,7 +68,7 @@ class Meta: default=dict, blank=True, validators=[_validate_reports] ) - def flag_spam(self): + def flag_spam(self, **kwargs): # If ham and unedited then tell user that they should read it again if self.spam_status == SpamStatus.UNKNOWN: self.spam_status = SpamStatus.FLAGGED diff --git a/osf/models/user.py b/osf/models/user.py index c49eeb41814..6b19a5e6f8d 100644 --- a/osf/models/user.py +++ b/osf/models/user.py @@ -18,6 +18,7 @@ from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager from django.contrib.auth.hashers import check_password from django.contrib.auth.models import PermissionsMixin +from django.core.exceptions import FieldDoesNotExist from django.dispatch import receiver from django.db import models from django.db.models import Count, Exists, OuterRef @@ -1460,15 +1461,18 @@ def confirm_email(self, token, merge=False): return True - def confirm_spam(self, domains=None, save=True, train_spam_services=False): + def confirm_spam(self, domains=None, save=True, train_spam_services=False, skip_resources_spam=False): self.deactivate_account() super().confirm_spam(domains=domains, save=save, train_spam_services=train_spam_services) + if skip_resources_spam: + return + # Don't train on resources merely associated with spam user for node in self.nodes.filter(is_public=True, is_deleted=False): - node.confirm_spam(train_spam_services=train_spam_services) + node.confirm_spam(domains=domains, train_spam_services=train_spam_services) for preprint in self.preprints.filter(is_public=True, deleted__isnull=True): - preprint.confirm_spam(train_spam_services=train_spam_services) + preprint.confirm_spam(domains=domains, train_spam_services=train_spam_services) def confirm_ham(self, save=False, train_spam_services=False): self.reactivate_account() @@ -2020,14 +2024,12 @@ def gdpr_delete(self): """ Complies with GDPR guidelines by disabling the account and removing identifying information. """ - - # Check if user has something intentionally public, like preprints or registrations - self._validate_no_public_entities() - - # Check if user has any non-registration AbstractNodes or DraftRegistrations that they might still share with - # other contributors self._validate_and_remove_resource_for_gdpr_delete( - self.nodes.exclude(type='osf.registration'), # Includes DraftNodes and other typed nodes + self.nodes.all(), + hard_delete=False + ) + self._validate_and_remove_resource_for_gdpr_delete( + self.preprints.all(), hard_delete=False ) self._validate_and_remove_resource_for_gdpr_delete( @@ -2038,39 +2040,6 @@ def gdpr_delete(self): # Finally delete the user's info. self._clear_identifying_information() - def _validate_no_public_entities(self): - """ - Ensure that the user doesn't have any public facing resources like Registrations or Preprints - that would be left with other contributors after this deletion. - - Allow GDPR deletion if the user is the sole contributor on a public Registration or Preprint. - """ - from osf.models import Preprint, AbstractNode - - registrations_with_others = AbstractNode.objects.annotate( - contrib_count=Count('_contributors', distinct=True), - ).filter( - _contributors=self, - deleted__isnull=True, - type='osf.registration', - contrib_count__gt=1 - ).exists() - - if registrations_with_others: - raise UserStateError('You cannot delete this user because they have one or more registrations.') - - preprints_with_others = Preprint.objects.annotate( - contrib_count=Count('_contributors', distinct=True), - ).filter( - _contributors=self, - ever_public=True, - deleted__isnull=True, - contrib_count__gt=1 - ).exists() - - if preprints_with_others: - raise UserStateError('You cannot delete this user because they have one or more preprints.') - def _validate_and_remove_resource_for_gdpr_delete(self, resources, hard_delete): """ This method ensures a user's resources are properly deleted of using during GDPR delete request. @@ -2095,18 +2064,23 @@ def _validate_and_remove_resource_for_gdpr_delete(self, resources, hard_delete): ) shared_resources = resources.exclude(id__in=personal_resources.values_list('id')) - for node in shared_resources: - self._validate_admin_status_for_gdpr_delete(node) - self._validate_addons_for_gdpr_delete(node) + for resource in shared_resources: + self._validate_admin_status_for_gdpr_delete(resource) + self._validate_addons_for_gdpr_delete(resource) for resource in shared_resources.all(): logger.info(f'Removing {self._id} as a contributor to {resource.__class__.__name__} (pk:{resource.pk})...') resource.remove_contributor(self, auth=Auth(self), log=False) + if getattr(resource, 'is_public', False) and hasattr(resource, 'update_search'): + resource.update_search() - # Delete all personal entities (excluding public registrations) + # Delete all personal non-public entities personal_to_delete = personal_resources - if hasattr(model, 'is_public') and hasattr(model, 'type'): - personal_to_delete = personal_to_delete.exclude(is_public=True, type='osf.registration') + try: + if model._meta.get_field('is_public'): + personal_to_delete = personal_to_delete.exclude(is_public=True) + except FieldDoesNotExist: + pass for entity in personal_to_delete.all(): if hard_delete: @@ -2114,7 +2088,11 @@ def _validate_and_remove_resource_for_gdpr_delete(self, resources, hard_delete): entity.delete() else: logger.info(f'Soft-deleting {entity.__class__.__name__} (pk: {entity.pk})...') - entity.remove_node(auth=Auth(self)) + if hasattr(entity, 'remove_node'): + entity.remove_node(auth=Auth(self)) + else: + entity.is_deleted = True + entity.save() def _clear_identifying_information(self): ''' diff --git a/osf/utils/permissions.py b/osf/utils/permissions.py index 76b656856fa..15ec2595a46 100644 --- a/osf/utils/permissions.py +++ b/osf/utils/permissions.py @@ -72,3 +72,7 @@ def check_private_key_for_anonymized_link(private_key): except PrivateLink.DoesNotExist: return False return link.anonymous + + +def get_contributor_proposed_permissions(validated_data): + return validated_data.get('permission') or DEFAULT_CONTRIBUTOR_PERMISSIONS diff --git a/osf_tests/external/akismet/test_akismet.py b/osf_tests/external/akismet/test_akismet.py index 95b119c2651..d9c7cb2ec63 100644 --- a/osf_tests/external/akismet/test_akismet.py +++ b/osf_tests/external/akismet/test_akismet.py @@ -140,7 +140,7 @@ def test_do_spam_check_true(self, mock_akismet, user, request_headers): user.do_check_spam( author='test-author', - author_email='test@test.com', + author_email=user.username, content='test', request_headers=request_headers ) @@ -148,7 +148,7 @@ def test_do_spam_check_true(self, mock_akismet, user, request_headers): data = parse_qs(mock_akismet.calls[0].request.body) assert data['comment_author'] == ['test-author'] - assert data['comment_author_email'] == ['test@test.com'] + assert data['comment_author_email'] == [user.username] assert data['blog'] == [settings.DOMAIN] user.refresh_from_db() diff --git a/osf_tests/external/oopspam/test_oopspam.py b/osf_tests/external/oopspam/test_oopspam.py index b4300875a76..79b6bfe179e 100644 --- a/osf_tests/external/oopspam/test_oopspam.py +++ b/osf_tests/external/oopspam/test_oopspam.py @@ -98,7 +98,7 @@ def test_do_spam_check_true(self, mock_oopspam, user, request_headers): user.do_check_spam( author='test-author', - author_email='test@test.com', + author_email=user.username, content='test', request_headers=request_headers ) @@ -119,7 +119,7 @@ def test_do_spam_check_false(self, mock_oopspam, user, request_headers): user.do_check_spam( author='test-author', - author_email='test@test.com', + author_email=user.username, content='test', request_headers=request_headers ) diff --git a/osf_tests/test_generate_sitemap.py b/osf_tests/test_generate_sitemap.py index a84bb1bdcfd..675901b7922 100644 --- a/osf_tests/test_generate_sitemap.py +++ b/osf_tests/test_generate_sitemap.py @@ -125,6 +125,33 @@ def preprint_other(self, project_preprint_other, user_admin_project_public, prov creator=user_admin_project_public, provider=provider_other) + @pytest.fixture(autouse=True) + def project_spammed(self, user_admin_project_public): + project = ProjectFactory(creator=user_admin_project_public, is_public=True) + project.confirm_spam(save=True, train_spam_services=False) + return project + + @pytest.fixture(autouse=True) + def preprint_spammed(self, project_preprint_osf, user_admin_project_public, provider_osf): + preprint = PreprintFactory( + project=project_preprint_osf, + creator=user_admin_project_public, + provider=provider_osf + ) + preprint.confirm_spam(save=True, train_spam_services=False) + return preprint + + @pytest.fixture(autouse=True) + def registration_spammed(self, user_admin_project_public, project_registration_public): + registration = RegistrationFactory( + project=project_registration_public, + creator=user_admin_project_public, + is_public=True + ) + # Flag the registration as spam + registration.confirm_spam(save=True, train_spam_services=False) + return registration + @pytest.fixture(autouse=True) def all_included_links(self, user_admin_project_public, user_admin_project_private, project_registration_public, project_preprint_osf, project_preprint_other, @@ -199,3 +226,23 @@ def test_deleted_project_link_not_included(self, project_deleted, create_tmp_dir urls = get_all_sitemap_urls() assert urljoin(settings.DOMAIN, project_deleted.url + 'overview') not in urls + + def test_spammed_project_link_not_included(self, project_spammed, create_tmp_directory): + with mock.patch('website.settings.STATIC_FOLDER', create_tmp_directory): + urls = get_all_sitemap_urls() + + assert urljoin(settings.DOMAIN, project_spammed.url + 'overview') not in urls + + def test_spammed_preprint_link_not_included(self, preprint_spammed, provider_osf, create_tmp_directory): + with mock.patch('website.settings.STATIC_FOLDER', create_tmp_directory): + urls = get_all_sitemap_urls() + + spammed_url = urljoin(settings.DOMAIN, f'/preprints/{provider_osf._id}/{preprint_spammed._id}') + assert spammed_url not in urls + + def test_spammed_registration_link_not_included(self, registration_spammed, create_tmp_directory): + with mock.patch('website.settings.STATIC_FOLDER', create_tmp_directory): + urls = get_all_sitemap_urls() + + # Verify the spammed registration's overview page does not make it into the XML + assert urljoin(settings.DOMAIN, registration_spammed.url + 'overview') not in urls diff --git a/osf_tests/test_guid.py b/osf_tests/test_guid.py index 1eb7ceea9ee..276ceecb05a 100644 --- a/osf_tests/test_guid.py +++ b/osf_tests/test_guid.py @@ -1,14 +1,11 @@ from unittest import mock -from urllib.parse import quote -from django.utils import timezone from django.core.exceptions import MultipleObjectsReturned import pytest from framework.auth import Auth from osf.models import Guid, GuidVersionsThrough, NodeLicenseRecord, OSFUser, Preprint from osf.models.base import VersionedGuidMixin -from osf.utils.permissions import ADMIN from osf_tests.factories import ( AuthUserFactory, NodeFactory, @@ -19,9 +16,6 @@ UserFactory, ) from tests.base import OsfTestCase -from tests.test_websitefiles import TestFile -from tests.utils import capture_notifications -from website.settings import MFR_SERVER_URL, WATERBUTLER_URL @pytest.mark.django_db @@ -235,238 +229,6 @@ def test_resolve_guid_private_request_access_or_redirect_to_cas(self): assert res.status_code == 403 assert 'OSF | Request Access' in res.text - def test_resolve_guid_download_file(self): - pp = PreprintFactory(finish=True) - - res = self.app.get(pp.url + 'download') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - res = self.app.get(pp.url + 'download/') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - res = self.app.get(f'/{pp.primary_file.get_guid(create=True)._id}/download') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - pp.primary_file.create_version( - creator=pp.creator, - location={'folder': 'osf', 'object': 'deadbe', 'service': 'cloud'}, - metadata={'contentType': 'img/png', 'size': 9001} - ) - pp.primary_file.save() - - res = self.app.get(pp.url + 'download/') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=2' in res.location - - res = self.app.get(pp.url + 'download/?version=1') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?version=1&action=download&direct' in res.location - - unpub_pp = PreprintFactory(project=self.node, is_published=False) - res = self.app.get(unpub_pp.url + 'download/?version=1', auth=unpub_pp.creator.auth) - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{unpub_pp._id}/providers/{unpub_pp.primary_file.provider}{unpub_pp.primary_file.path}?version=1&action=download&direct' in res.location - - @mock.patch('website.settings.USE_EXTERNAL_EMBER', True) - @mock.patch('website.settings.EXTERNAL_EMBER_APPS', { - 'preprints': { - 'server': 'http://localhost:4200', - 'path': '/preprints/' - }, - }) - def test_resolve_guid_download_file_from_emberapp_preprints(self): - provider = PreprintProviderFactory(_id='sockarxiv', name='Sockarxiv') - pp = PreprintFactory(finish=True, provider=provider) - assert pp.url.startswith('/preprints/sockarxiv') - - res = self.app.get(pp.url + 'download') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - res = self.app.get(pp.url + 'download/') - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - @mock.patch('website.settings.USE_EXTERNAL_EMBER', True) - @mock.patch('website.settings.EXTERNAL_EMBER_APPS', { - 'preprints': { - 'server': 'http://localhost:4200', - 'path': '/preprints/' - }, - }) - def test_resolve_guid_download_file_from_emberapp_preprints_unpublished(self): - # non-branded domains - provider = PreprintProviderFactory(_id='sockarxiv', name='Sockarxiv', reviews_workflow='pre-moderation') - - # branded domains - branded_provider = PreprintProviderFactory(_id='spot', name='Spotarxiv', reviews_workflow='pre-moderation') - branded_provider.allow_submissions = False - branded_provider.domain = 'https://www.spotarxiv.com' - branded_provider.description = 'spots not dots' - branded_provider.domain_redirect_enabled = True - branded_provider.share_publish_type = 'Thesis' - branded_provider.save() - - # test_provider_submitter_can_download_unpublished - submitter = AuthUserFactory() - pp = PreprintFactory(finish=True, provider=provider, is_published=False, creator=submitter) - with capture_notifications(): - pp.run_submit(submitter) - pp_branded = PreprintFactory(finish=True, provider=branded_provider, is_published=False, filename='preprint_file_two.txt', creator=submitter) - with capture_notifications(): - pp_branded.run_submit(submitter) - - res = self.app.get(f'{pp.url}download', auth=submitter.auth) - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - res = self.app.get(f'{pp_branded.url}download', auth=submitter.auth) - assert res.status_code == 302 - - # test_provider_super_user_can_download_unpublished - super_user = AuthUserFactory() - super_user.is_superuser = True - super_user.save() - - res = self.app.get(f'{pp.url}download', auth=super_user.auth) - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - res = self.app.get(f'{pp_branded.url}download', auth=super_user.auth) - assert res.status_code == 302 - - # test_provider_moderator_can_download_unpublished - moderator = AuthUserFactory() - provider.add_to_group(moderator, 'moderator') - provider.save() - - res = self.app.get(f'{pp.url}download', auth=moderator.auth) - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - branded_provider.add_to_group(moderator, 'moderator') - branded_provider.save() - - res = self.app.get(f'{pp_branded.url}download', auth=moderator.auth) - assert res.status_code == 302 - - # test_provider_admin_can_download_unpublished - admin = AuthUserFactory() - provider.add_to_group(admin, ADMIN) - provider.save() - - res = self.app.get(f'{pp.url}download', auth=admin.auth) - assert res.status_code == 302 - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?action=download&direct&version=1' in res.location - - branded_provider.add_to_group(admin, ADMIN) - branded_provider.save() - - res = self.app.get(f'{pp_branded.url}download', auth=admin.auth) - assert res.status_code == 302 - - def test_resolve_guid_download_file_export(self): - pp = PreprintFactory(finish=True) - - res = self.app.get(pp.url + 'download?format=asdf') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}%3Fformat%3Dasdf%26action%3Ddownload%26direct%26version%3D1' in res.location - - res = self.app.get(pp.url + 'download/?format=asdf') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}%3Fformat%3Dasdf%26action%3Ddownload%26direct%26version%3D1' in res.location - - res = self.app.get(f'/{pp.primary_file.get_guid(create=True)._id}/download?format=asdf') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}%3Fformat%3Dasdf%26action%3Ddownload%26direct%26version%3D1' in res.location - - res = self.app.get(f'/{pp.primary_file.get_guid(create=True)._id}/download/?format=asdf') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}%3Fformat%3Dasdf%26action%3Ddownload%26direct%26version%3D1' in res.location - - pp.primary_file.create_version( - creator=pp.creator, - location={'folder': 'osf', 'object': 'deadbe', 'service': 'cloud'}, - metadata={'contentType': 'img/png', 'size': 9001} - ) - pp.primary_file.save() - - res = self.app.get(pp.url + 'download/?format=asdf') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}%3F' in res.location - quarams = res.location.split('%3F')[1].split('%26') - assert 'action%3Ddownload' in quarams - assert 'version%3D2' in quarams - assert 'direct' in quarams - - res = self.app.get(pp.url + 'download/?format=asdf&version=1') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}%3F' in res.location - quarams = res.location.split('%3F')[1].split('%26') - assert 'action%3Ddownload' in quarams - assert 'version%3D1' in quarams - assert 'direct' in quarams - - unpub_pp = PreprintFactory(project=self.node, is_published=False) - res = self.app.get(unpub_pp.url + 'download?format=asdf', auth=unpub_pp.creator.auth) - assert res.status_code == 302 - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?format=asdf&url=' in res.location - assert f'{quote(WATERBUTLER_URL)}/v1/resources/{unpub_pp._id}/providers/{unpub_pp.primary_file.provider}{unpub_pp.primary_file.path}%3F' in res.location - quarams = res.location.split('%3F')[1].split('%26') - assert 'action%3Ddownload' in quarams - assert 'version%3D1' in quarams - assert 'direct' in quarams - - def test_resolve_guid_download_file_export_same_format_optimization(self): - pp = PreprintFactory(filename='test.pdf', finish=True) - - res = self.app.get(pp.url + 'download/?format=pdf') - assert res.status_code == 302 - assert f'{MFR_SERVER_URL}/export?' not in res.location - assert f'{WATERBUTLER_URL}/v1/resources/{pp._id}/providers/{pp.primary_file.provider}{pp.primary_file.path}?format=pdf&action=download&direct&version=1' in res.location - - def test_resolve_guid_download_errors(self): - testfile = TestFile.get_or_create(self.node, 'folder/path') - testfile.name = 'asdf' - testfile.materialized_path = '/folder/path' - guid = testfile.get_guid(create=True) - testfile.save() - testfile.delete() - res = self.app.get(f'/{guid}/download') - assert res.status_code == 404 - - pp = PreprintFactory(is_published=False) - res = self.app.get(pp.url + 'download') - assert res.status_code == 404 - - pp.is_published = True - pp.save() - pp.is_public = False - pp.save() - - non_contrib = AuthUserFactory() - - res = self.app.get(pp.url + 'download', auth=non_contrib.auth) - assert res.status_code == 403 - - pp.deleted = timezone.now() - pp.save() - - res = self.app.get(pp.url + 'download', auth=non_contrib.auth) - assert res.status_code == 410 - def test_resolve_guid_redirect_to_versioned_guid(self): pp = PreprintFactory(filename='test.pdf', finish=True) diff --git a/osf_tests/test_gv_session_optimization.py b/osf_tests/test_gv_session_optimization.py index 5fdccffdc10..b94451e339d 100644 --- a/osf_tests/test_gv_session_optimization.py +++ b/osf_tests/test_gv_session_optimization.py @@ -376,7 +376,8 @@ def test_get_addon_uses_auth_user_id_when_request_user_id_is_none( mock_get_addon_from_gv.assert_called_once_with( gv_pk='github', requesting_user_id=user._id, - auth=auth + auth=auth, + cached=True ) assert result == mock_addon @@ -402,7 +403,8 @@ def test_get_addon_uses_request_user_id_when_available( mock_get_addon_from_gv.assert_called_once_with( gv_pk='github', requesting_user_id=request_user_id, - auth=auth + auth=auth, + cached=True ) assert result == mock_addon @@ -425,7 +427,8 @@ def test_get_addon_handles_none_auth_gracefully( mock_get_addon_from_gv.assert_called_once_with( gv_pk='github', requesting_user_id=None, - auth=None + auth=None, + cached=True ) assert result == mock_addon @@ -464,7 +467,8 @@ def test_get_addon_with_auth_user_none_falls_back_to_request_user_id( mock_get_addon_from_gv.assert_called_once_with( gv_pk='github', requesting_user_id=request_user_id, - auth=auth + auth=auth, + cached=True ) assert result == mock_addon diff --git a/osf_tests/test_node.py b/osf_tests/test_node.py index e78876b1fed..98447188a8b 100644 --- a/osf_tests/test_node.py +++ b/osf_tests/test_node.py @@ -2414,6 +2414,18 @@ def user(self): def project(self, user): return ProjectFactory(creator=user) + @pytest.fixture() + def project2(self, user): + return ProjectFactory(creator=user) + + @pytest.fixture() + def project3(self, user): + return ProjectFactory(creator=user) + + @pytest.fixture() + def preprint(self, user): + return PreprintFactory(creator=user) + @pytest.fixture() def request_headers(self): return { @@ -2422,6 +2434,109 @@ def request_headers(self): 'Referer': 'https://osf.io' } + def run_akismet_and_oops_tests( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed=None): + """ + This method makes the next checks when akismet and oopsystem are used: + 1. A resource and its creator become FLAGGED and other public nodes/preprints of this creator become SPAMMED and contain the same spam data + 2. Private nodes/preprints don't contain spam data + 3. If akismet confirms spam, all objects from #1 have spam_pro_tip + 4. If oopspam confirms spam, all objects from #1 have oopspam_data key in spam_data + 5. who_flagged property in spam_data contains either service name (akismet or oopspam) or 'both' value + 6. spam_data of objects from #1 contains headers, request user info and spammy content + + Params: + spam_object - object that is being checked for spam + akismet_spam_data - spam data returned by akismet + oops_spam_data - spam data returned by oopsystem + objects_to_be_spammed - objects to be spammed instead of flagged. Example: + spam_object = Node + spam objects is flagged, its creator is flagged and the others user's public nodes/preprints must be spammed + """ + project.set_privacy('public') + project2.set_privacy('public') + mock_check_domains.return_value = [] + + author = user.fullname + author_email = user.username + content = 'Check me for spam with akismet and oops' + objects_to_be_spammed = objects_to_be_spammed or [] + + # configurable part + spam_object = spam_object + akismet_spam_data = akismet_spam_data + oops_spam_data = oops_spam_data + + if akismet_spam_data and oops_spam_data: + expected_who_flagged = 'both' + elif akismet_spam_data: + expected_who_flagged = 'akismet' + elif oops_spam_data: + expected_who_flagged = 'oopspam' + else: + expected_who_flagged = None + + if akismet_spam_data or oops_spam_data: + expected_spam_data = { + 'headers': request_headers, + 'author': author, + 'author_email': author_email, + 'content': content, + 'who_flagged': expected_who_flagged + } + if oops_spam_data: + expected_spam_data['oopspam_data'] = oops_spam_data + else: + expected_spam_data = {} + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (bool(akismet_spam_data), akismet_spam_data) + mock_oops_check_content.return_value = (bool(oops_spam_data), oops_spam_data) + with capture_notifications(allow_none=True): + spam_tasks.check_resource_for_spam_postcommit( + guid=spam_object._id, + content=content, + author=author, + author_email=author_email, + request_headers=request_headers + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + for obj in [user, project, project2, preprint]: + if akismet_spam_data or oops_spam_data: + if obj in objects_to_be_spammed: + assert obj.spam_status == SpamStatus.SPAM + else: + assert obj.spam_status == SpamStatus.FLAGGED + + assert obj.spam_data == expected_spam_data + else: + assert obj.spam_status is None + assert obj.spam_data == {} + assert obj.spam_pro_tip is None + + if mock_akismet_check_content.return_value[0] and mock_oops_check_content.return_value[0]: + assert obj.spam_pro_tip == akismet_spam_data + assert obj.spam_data.get('oopspam_data', {}) == oops_spam_data + elif mock_akismet_check_content.return_value[0]: + assert obj.spam_pro_tip == akismet_spam_data + assert 'oopspam_data' not in obj.spam_data + elif mock_oops_check_content.return_value[0]: + assert obj.spam_data.get('oopspam_data', {}) == oops_spam_data + assert obj.spam_pro_tip is None + + # private node shouldn't be spammed + assert project3.spam_status is None + assert project3.spam_pro_tip is None + assert project3.spam_data == {} + + assert user.spam_data == project.spam_data == project2.spam_data == preprint.spam_data + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) @mock.patch('osf.external.spam.tasks._check_resource_for_domains') def test_check_resource_for_spam_postcommit_with_spammy_domains(self, mock_check_domains, project, user): @@ -2489,7 +2604,850 @@ def test_check_resource_for_spam_postcommit_checks_user(self, mock_check_domains author_email=user.username, request_headers=request_headers ) - mock_check_user.assert_called_once_with(user) + mock_check_user.assert_called_once_with(user, domains=[]) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_because_of_spammy_domains(self, mock_check_domains, user, project, preprint): + user.date_confirmed = timezone.now() + user.save() + + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = ['spam_domain.com'] + + project.set_privacy('public') + + spam_tasks.check_resource_for_spam_postcommit( + guid=user._id, + content='Check me for spam at spam_domain.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.UNKNOWN + assert preprint.spam_data == {} + + assert project.spam_status == SpamStatus.UNKNOWN + assert project.spam_data == {} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_creator_is_not_spammed_because_of_spammy_domains_in_node(self, mock_check_domains, user, project, preprint): + user.date_confirmed = timezone.now() + user.save() + + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = ['spam_domain.com'] + + project.set_privacy('public') + + spam_tasks.check_resource_for_spam_postcommit( + guid=project._id, + content='Check me for spam at spam_domain.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.UNKNOWN + assert preprint.spam_data == {} + + assert project.spam_status == SpamStatus.SPAM + assert project.spam_data['domains'] == ['spam_domain.com'] + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_creator_is_not_spammed_because_of_spammy_domains_in_preprint(self, mock_check_domains, user, project, preprint): + user.date_confirmed = timezone.now() + user.save() + + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = ['spam_domain.com'] + + project.set_privacy('public') + + spam_tasks.check_resource_for_spam_postcommit( + guid=preprint._id, + content='Check me for spam at spam_domain.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.SPAM + assert preprint.spam_data['domains'] == ['spam_domain.com'] + + assert project.spam_status == SpamStatus.UNKNOWN + assert project.spam_data == {} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_spammed_user_shares_spam_data_with_nodes_and_preprints(self, mock_check_domains, user, project, preprint): + user.date_confirmed = timezone.now() + user.save() + + mock_check_domains.return_value = ['spam_domain.com'] + + project.set_privacy('public') + + spam_tasks.check_resource_for_spam_postcommit( + guid=user._id, + content='Check me for spam at spam_domain.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.SPAM + assert user.spam_data['domains'] == ['spam_domain.com'] + + assert preprint.spam_status == SpamStatus.SPAM + assert preprint.spam_data['domains'] == ['spam_domain.com'] + + assert project.spam_status == SpamStatus.SPAM + assert project.spam_data['domains'] == ['spam_domain.com'] + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_spammed_project_shares_spam_data_with_creator_and_other_nodes_and_preprints(self, mock_check_domains, user, project, preprint): + user.date_confirmed = timezone.now() + user.save() + + project2 = ProjectFactory(creator=user) + project2.set_privacy('public') + + mock_check_domains.return_value = ['again_spam.com'] + + with capture_notifications(): + spam_tasks.check_resource_for_spam_postcommit( + guid=project._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert project.spam_status == SpamStatus.SPAM + assert project.spam_data['domains'] == ['again_spam.com'] + + assert project2.spam_status == SpamStatus.SPAM + assert project2.spam_data['domains'] == ['again_spam.com'] + + assert preprint.spam_status == SpamStatus.SPAM + assert preprint.spam_data['domains'] == ['again_spam.com'] + + assert user.spam_status == SpamStatus.SPAM + assert user.spam_data['domains'] == ['again_spam.com'] + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_spammed_preprint_shares_spam_data_with_creator_and_other_nodes_and_preprints(self, mock_check_domains, user, project, preprint): + user.date_confirmed = timezone.now() + user.save() + + project2 = ProjectFactory(creator=user) + project2.set_privacy('public') + + preprint2 = PreprintFactory(creator=user) + + mock_check_domains.return_value = ['again_spam.com'] + + with capture_notifications(): + spam_tasks.check_resource_for_spam_postcommit( + guid=preprint._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + preprint2.reload() + + # project is private + assert project.spam_status != SpamStatus.SPAM + assert 'domains' not in project.spam_data + + assert project2.spam_status == SpamStatus.SPAM + assert project2.spam_data['domains'] == ['again_spam.com'] + + assert preprint.spam_status == SpamStatus.SPAM + assert preprint.spam_data['domains'] == ['again_spam.com'] + + assert preprint2.spam_status == SpamStatus.SPAM + assert preprint2.spam_data['domains'] == ['again_spam.com'] + + assert user.spam_status == SpamStatus.SPAM + assert user.spam_data['domains'] == ['again_spam.com'] + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_akismet_detected_spam( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (True, 'spam_data') + mock_oops_check_content.return_value = (False, {}) + spam_tasks.check_resource_for_spam_postcommit( + guid=user._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.UNKNOWN + assert preprint.spam_pro_tip is None + assert preprint.spam_data == {} + + assert project.spam_status == SpamStatus.UNKNOWN + assert project.spam_pro_tip is None + assert project.spam_data == {} + + assert project2.spam_status == SpamStatus.UNKNOWN + assert project2.spam_pro_tip is None + assert project2.spam_data == {} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_akismet_detected_spam_in_node( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (True, 'spam_data') + mock_oops_check_content.return_value = (False, {}) + spam_tasks.check_resource_for_spam_postcommit( + guid=project._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_pro_tip is None + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.FLAGGED + assert preprint.spam_pro_tip == 'spam_data' + + assert project.spam_status == SpamStatus.FLAGGED + assert project.spam_pro_tip == 'spam_data' + + assert project2.spam_status == SpamStatus.FLAGGED + assert project2.spam_pro_tip == 'spam_data' + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_akismet_detected_spam_in_preprint( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (True, 'spam_data') + mock_oops_check_content.return_value = (False, {}) + spam_tasks.check_resource_for_spam_postcommit( + guid=preprint._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_pro_tip is None + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.FLAGGED + assert preprint.spam_pro_tip == 'spam_data' + + assert project.spam_status == SpamStatus.FLAGGED + assert project.spam_pro_tip == 'spam_data' + + assert project2.spam_status == SpamStatus.FLAGGED + assert project2.spam_pro_tip == 'spam_data' + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_oops_detected_spam( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (False, '') + mock_oops_check_content.return_value = (True, {'reason': 'spam'}) + spam_tasks.check_resource_for_spam_postcommit( + guid=user._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.UNKNOWN + assert preprint.spam_data == {} + + assert project.spam_status == SpamStatus.UNKNOWN + assert project.spam_data == {} + + assert project2.spam_status == SpamStatus.UNKNOWN + assert project2.spam_data == {} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_oops_detected_spam_in_node( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (False, '') + mock_oops_check_content.return_value = (True, {'reason': 'spam'}) + spam_tasks.check_resource_for_spam_postcommit( + guid=project._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.FLAGGED + assert preprint.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project.spam_status == SpamStatus.FLAGGED + assert project.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project2.spam_status == SpamStatus.FLAGGED + assert project2.spam_data['oopspam_data'] == {'reason': 'spam'} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_oops_detected_spam_in_preprint( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (False, '') + mock_oops_check_content.return_value = (True, {'reason': 'spam'}) + spam_tasks.check_resource_for_spam_postcommit( + guid=preprint._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.FLAGGED + assert preprint.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project.spam_status == SpamStatus.FLAGGED + assert project.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project2.spam_status == SpamStatus.FLAGGED + assert project2.spam_data['oopspam_data'] == {'reason': 'spam'} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_akismet_and_oops_detected_spam( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (True, 'akismet spam data') + mock_oops_check_content.return_value = (True, {'reason': 'spam'}) + spam_tasks.check_resource_for_spam_postcommit( + guid=user._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_pro_tip is None + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.UNKNOWN + assert preprint.spam_pro_tip is None + assert preprint.spam_data == {} + + assert project.spam_status == SpamStatus.UNKNOWN + assert project.spam_pro_tip is None + assert project.spam_data == {} + + assert project2.spam_status == SpamStatus.UNKNOWN + assert project2.spam_pro_tip is None + assert project2.spam_data == {} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_akismet_and_oops_detected_spam_in_node( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (True, 'akismet spam data') + mock_oops_check_content.return_value = (True, {'reason': 'spam'}) + spam_tasks.check_resource_for_spam_postcommit( + guid=project._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_pro_tip is None + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.FLAGGED + assert preprint.spam_pro_tip == 'akismet spam data' + assert preprint.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project.spam_status == SpamStatus.FLAGGED + assert project.spam_pro_tip == 'akismet spam data' + assert project.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project2.spam_status == SpamStatus.FLAGGED + assert project2.spam_pro_tip == 'akismet spam data' + assert project2.spam_data['oopspam_data'] == {'reason': 'spam'} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_ham_user_is_not_spammed_when_akismet_and_oops_detected_spam_in_preprint( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.spam_status = SpamStatus.HAM + user.save() + + mock_check_domains.return_value = [] + + project.set_privacy('public') + project2.set_privacy('public') + + with mock.patch('osf.external.spam.tasks.AkismetClient.check_content') as mock_akismet_check_content: + with mock.patch('osf.external.spam.tasks.OOPSpamClient.check_content') as mock_oops_check_content: + mock_akismet_check_content.return_value = (True, 'akismet spam data') + mock_oops_check_content.return_value = (True, {'reason': 'spam'}) + spam_tasks.check_resource_for_spam_postcommit( + guid=preprint._id, + content='Check me for spam at again_spam.com', + author=user.fullname, + author_email=user.username, + request_headers={} + ) + user.reload() + project.reload() + project2.reload() + preprint.reload() + + assert user.spam_status == SpamStatus.HAM + assert user.spam_pro_tip is None + assert user.spam_data == {} + + assert preprint.spam_status == SpamStatus.FLAGGED + assert preprint.spam_pro_tip == 'akismet spam data' + assert preprint.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project.spam_status == SpamStatus.FLAGGED + assert project.spam_pro_tip == 'akismet spam data' + assert project.spam_data['oopspam_data'] == {'reason': 'spam'} + + assert project2.spam_status == SpamStatus.FLAGGED + assert project2.spam_pro_tip == 'akismet spam data' + assert project2.spam_data['oopspam_data'] == {'reason': 'spam'} + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_no_spam_found_by_akismet_and_oopspam_for_user( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + spam_object = user + akismet_spam_data = '' + oops_spam_data = {} + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_no_spam_found_by_akismet_and_oopspam_for_node( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + spam_object = project + akismet_spam_data = '' + oops_spam_data = {} + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_no_spam_found_by_akismet_and_oopspam_for_preprint( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + spam_object = preprint + akismet_spam_data = '' + oops_spam_data = {} + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_akismet_spammed_user_shares_spam_data_with_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + spam_object = user + akismet_spam_data = 'It is a spammy content, spam it!' + oops_spam_data = {} + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_oops_spammed_user_shares_spam_data_with_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + spam_object = user + akismet_spam_data = '' + oops_spam_data = {'reason': 'spam'} + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_akismet_and_oops_spammed_user_shares_spam_data_with_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + spam_object = user + akismet_spam_data = 'some spam found' + oops_spam_data = {'reason': 'spam'} + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_akismet_spammed_node_shares_spam_data_with_creator_and_other_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.date_confirmed = timezone.now() + user.save() + + spam_object = project + akismet_spam_data = 'some spam found' + oops_spam_data = {} + objects_to_be_spammed = [user, project2, preprint] + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_oops_spammed_node_shares_spam_data_with_creator_and_other_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.date_confirmed = timezone.now() + user.save() + + spam_object = project + akismet_spam_data = '' + oops_spam_data = {'reason': 'some spam info'} + objects_to_be_spammed = [user, project2, preprint] + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_akismet_and_oops_spammed_node_shares_spam_data_with_creator_and_other_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.date_confirmed = timezone.now() + user.save() + + spam_object = project + akismet_spam_data = 'it is a real spam!!!' + oops_spam_data = {'reason': 'some spam info'} + objects_to_be_spammed = [user, project2, preprint] + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_akismet_spammed_preprint_shares_spam_data_with_creator_and_other_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.date_confirmed = timezone.now() + user.save() + + spam_object = preprint + akismet_spam_data = 'some spam found' + oops_spam_data = {} + objects_to_be_spammed = [user, project2, project] + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_oops_spammed_preprint_shares_spam_data_with_creator_and_other_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.date_confirmed = timezone.now() + user.save() + + spam_object = preprint + akismet_spam_data = '' + oops_spam_data = {'reason': 'some spam info'} + objects_to_be_spammed = [user, project2, project] + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed + ) + + @mock.patch.object(settings, 'SPAM_ACCOUNT_SUSPENSION_ENABLED', True) + @mock.patch.object(settings, 'SPAM_SERVICES_ENABLED', True) + @mock.patch.object(settings, 'AKISMET_ENABLED', True) + @mock.patch.object(settings, 'OOPSPAM_ENABLED', True) + @mock.patch('osf.external.spam.tasks._check_resource_for_domains') + def test_akismet_and_oops_spammed_preprint_shares_spam_data_with_creator_and_other_nodes_and_preprints( + self, mock_check_domains, user, project, project2, project3, preprint, request_headers + ): + user.date_confirmed = timezone.now() + user.save() + + spam_object = preprint + akismet_spam_data = 'it is a real spam!!!' + oops_spam_data = {'reason': 'some spam info'} + objects_to_be_spammed = [user, project2, project] + self.run_akismet_and_oops_tests( + mock_check_domains, user, project, project2, project3, preprint, request_headers, + spam_object, akismet_spam_data, oops_spam_data, objects_to_be_spammed + ) # copied from tests/test_models.py diff --git a/osf_tests/test_user.py b/osf_tests/test_user.py index 6bccb40e9dd..2e5d0631cd4 100644 --- a/osf_tests/test_user.py +++ b/osf_tests/test_user.py @@ -507,8 +507,8 @@ def test_add_blocked_domain_unconfirmed_email(self, user): def test_get_confirmation_url_for_external_service(self, random_string): random_string.return_value = 'abcde' u = UnconfirmedUserFactory() - assert (u.get_confirmation_url(u.username, external_id_provider='service', destination='dashboard') == - f'{settings.DOMAIN}confirm/external/{u._id}/abcde/?destination=dashboard') + assert (u.get_confirmation_url(u.username, external_id_provider='service', destination='my_projects') == + f'{settings.DOMAIN}confirm/external/{u._id}/abcde/?destination=my_projects') @mock.patch('website.security.random_string') def test_get_confirmation_token(self, random_string): @@ -2143,6 +2143,37 @@ def project_user_is_only_admin(self, user): project.save() return project + @mock.patch('osf.models.node.AbstractNode.update_search') + def test_gdpr_delete_triggers_share_update_for_public_shared_nodes( + self, mock_update_search, user, project_with_two_admins): + project_with_two_admins.is_public = True + project_with_two_admins.save() + + user.gdpr_delete() + + assert mock_update_search.called + + @mock.patch('osf.models.node.AbstractNode.update_search') + def test_gdpr_delete_does_not_trigger_share_update_for_non_public_shared_nodes( + self, mock_update_search, user, project_with_two_admins): + assert project_with_two_admins.is_public is False + + user.gdpr_delete() + + assert not mock_update_search.called + + @mock.patch('osf.models.preprint.Preprint.update_search') + def test_gdpr_delete_triggers_share_update_for_public_shared_preprints( + self, mock_update_search, user, preprint): + other_user = AuthUserFactory() + preprint.add_contributor(other_user, auth=Auth(user), permissions='admin') + preprint.save() + assert preprint.is_public is True + + user.gdpr_delete() + + assert mock_update_search.called + def test_can_gdpr_delete(self, user): user.social = ['fake social'] user.schools = ['fake schools'] @@ -2184,7 +2215,7 @@ def test_can_gdpr_delete_shared_draft_registration_with_multiple_admins(self, us assert draft_registrations.contributors.get() == other_admin assert user.nodes.filter(deleted__isnull=True).count() == 0 - def test_cant_gdpr_delete_multiple_contributors_registrations(self, user, registration): + def test_gdpr_delete_removes_user_from_shared_registrations(self, user, registration): registration.is_public = True other_user = AuthUserFactory() registration.add_contributor(other_user, auth=Auth(user), permissions='admin') @@ -2192,20 +2223,28 @@ def test_cant_gdpr_delete_multiple_contributors_registrations(self, user, regist assert registration.contributors.count() == 2 - with pytest.raises(UserStateError) as exc_info: - user.gdpr_delete() + user.gdpr_delete() + registration.reload() - assert exc_info.value.args[0] == 'You cannot delete this user because they have one or more registrations.' + assert registration.contributors.count() == 1 + assert registration.contributors.first() == other_user + assert not registration.is_deleted + assert user.deleted is not None - def test_cant_gdpr_delete_multiple_contributors_preprints(self, user, preprint): + def test_gdpr_delete_removes_user_from_shared_preprints(self, user, preprint): other_user = AuthUserFactory() preprint.add_contributor(other_user, auth=Auth(user), permissions='admin') preprint.save() - with pytest.raises(UserStateError) as exc_info: - user.gdpr_delete() + assert preprint.contributors.count() == 2 + + user.gdpr_delete() + preprint.reload() - assert exc_info.value.args[0] == 'You cannot delete this user because they have one or more preprints.' + assert preprint.contributors.count() == 1 + assert preprint.contributors.first() == other_user + assert not preprint.is_deleted + assert user.deleted is not None def test_can_gdpr_delete_sole_contributor_registration(self, user): registration = RegistrationFactory(creator=user) diff --git a/package.json b/package.json index c3b35461b3f..07ebfaed354 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,6 @@ "license": "Apache-2.0", "dependencies": { "@centerforopenscience/list-of-licenses": "^1.1.0", - "@centerforopenscience/markdown-it-atrules": "^0.1.1", - "@centerforopenscience/markdown-it-imsize": "2.0.1", - "@centerforopenscience/markdown-it-toc": "~1.1.1", - "@centerforopenscience/markdown-it-video": "1.0.0", "@centerforopenscience/osf-style": "1.9.0", "@fortawesome/fontawesome-free": "^7.0.1", "@fortawesome/fontawesome-svg-core": "^7.0.1", @@ -18,9 +14,6 @@ "@fortawesome/react-fontawesome": "^3.0.2", "URIjs": "^1.14.1", "assets-webpack-plugin": "^2.3.0", - "babel-core": "^6.0.0", - "babel-loader": "^6.4.1", - "body-parser": "~1.19.1", "bootbox": "^5.5.2", "bootstrap": "3.3.7", "bower": "^1.8.8", @@ -29,41 +22,33 @@ "dropzone": "https://github.com/CenterForOpenScience/dropzone.git#aba21eb6b82cc823ac7a7a53d6e035791c082bae", "exports-loader": "0.6.3", "file-loader": "^0.11.2", - "font-awesome-webpack": "0.0.5-beta.2", "gsap": "3.9.1", "highlight.js": "~9.18.2", "imports-loader": "^0.6.3", "js-cookie": "3.0.1", "js-md5": "^0.7.3", "jstimezonedetect": "^1.0.6", - "keen-dataviz": "^1.0.2", "knockout": "~3.4.2", "knockout.validation": "^2.0.2", "less": "^4.1.2", "linkifyjs": "^3.0.5", "loaders.css": "^0.1.2", - "lodash.chunk": "^4.0.6", "lodash.find": "^4.3.0", "lodash.get": "^4.2.1", "lodash.has": "^4.5.2", "lodash.includes": "^4.3.0", "lodash.set": "^4.3.2", - "markdown-it": "~12.3.2", - "markdown-it-ins-del": "^0.1.1", - "markdown-it-sanitizer": "~0.4.3", "mime-types": "~2.1.34", "mithril": "0.2.0", "moment": "^2.14.1", "object-assign": "^3.0.0", "pikaday": "^1.3.2", - "pretty-data": "^0.40.0", "raw-loader": "~0.5.0", "select2": "3.5.1", "style-loader": "^0.23.1", "treebeard": "https://github.com/CenterForOpenScience/treebeard.git#d2bb8f6f8104fcac040402727f431c26722b269e", "typeahead.js": "^0.11.1", "url-loader": "~0.6.2", - "uuid": "^8.3.2", "webpack": "3.12.0", "zxcvbn": "^4.2.0" }, @@ -73,8 +58,6 @@ }, "resolutions": { "bootbox/bootstrap": "^3.3.7", - "font-awesome-webpack/css-loader": "^0.28.11", - "font-awesome-webpack/style-loader": "^0.23.1", "treebeard/mithril": "0.2.0", "treebeard/bootstrap": "3.3.7", "webpack/uglifyjs-webpack-plugin": "1.3.0", diff --git a/scripts/check_manual_restart_approval.py b/scripts/check_manual_restart_approval.py new file mode 100644 index 00000000000..e9e6c70de0c --- /dev/null +++ b/scripts/check_manual_restart_approval.py @@ -0,0 +1,74 @@ +import logging +from framework.celery_tasks import app as celery_app +from django.core.management import call_command +from osf.models import Registration + +logger = logging.getLogger(__name__) + + +@celery_app.task(name='scripts.check_manual_restart_approval') +def check_manual_restart_approval(registration_id): + try: + try: + registration = Registration.objects.get(_id=registration_id) + except Registration.DoesNotExist: + logger.error(f"Registration {registration_id} not found") + return f"Registration {registration_id} not found" + + if registration.is_public or registration.is_registration_approved: + return f"Registration {registration_id} already approved/public" + + if registration.archiving: + logger.info(f"Registration {registration_id} still archiving, retrying in 10 minutes") + check_manual_restart_approval.apply_async( + args=[registration_id], + countdown=600 + ) + return f"Registration {registration_id} still archiving, scheduled retry" + + logger.info(f"Processing manual restart approval for registration {registration_id}") + + call_command( + 'process_manual_restart_approvals', + registration_id=registration_id, + dry_run=False, + hours_back=24, + verbosity=1 + ) + + return f"Processed manual restart approval check for registration {registration_id}" + + except Exception as e: + logger.error(f"Error processing manual restart approval for {registration_id}: {e}") + raise + + +@celery_app.task(name='scripts.check_manual_restart_approvals_batch') +def check_manual_restart_approvals_batch(hours_back=24): + try: + logger.info(f"Running batch check for manual restart approvals (last {hours_back} hours)") + + call_command( + 'process_manual_restart_approvals', + dry_run=False, + hours_back=hours_back, + verbosity=1 + ) + + return f"Completed batch manual restart approval check for last {hours_back} hours" + + except Exception as e: + logger.error(f"Error in batch manual restart approval check: {e}") + raise + + +@celery_app.task(name='scripts.delayed_manual_restart_approval') +def delayed_manual_restart_approval(registration_id, delay_minutes=30): + logger.info(f"Scheduling delayed manual restart approval check for {registration_id} in {delay_minutes} minutes") + + check_manual_restart_approval.apply_async( + args=[registration_id], + countdown=delay_minutes * 60 + ) + + return f"Scheduled manual restart approval check for {registration_id} in {delay_minutes} minutes" \ No newline at end of file diff --git a/scripts/enhanced_stuck_registration_audit.py b/scripts/enhanced_stuck_registration_audit.py new file mode 100644 index 00000000000..3905526ae52 --- /dev/null +++ b/scripts/enhanced_stuck_registration_audit.py @@ -0,0 +1,137 @@ +import logging + +from django.core.management import call_command +from framework.celery_tasks import app as celery_app +from osf.models import Registration +from osf.management.commands.force_archive import archive, DEFAULT_PERMISSIBLE_ADDONS +from scripts.stuck_registration_audit import analyze_failed_registration_nodes + +logger = logging.getLogger(__name__) + + +@celery_app.task(name='scripts.enhanced_stuck_registration_audit') +def enhanced_stuck_registration_audit(): + logger.info('Starting enhanced stuck registration audit') + + try: + logger.info('Processing pending manual restart approvals') + call_command('process_manual_restart_approvals', dry_run=False, hours_back=72) + except Exception as e: + logger.error(f"Error processing manual restart approvals: {e}") + + logger.info('Analyzing failed registrations') + failed_registrations = analyze_failed_registration_nodes() + + if not failed_registrations: + logger.info('No failed registrations found') + return 'No failed registrations found' + + logger.info(f"Found {len(failed_registrations)} failed registrations") + + auto_retryable = [] + needs_manual_intervention = [] + + for reg_info in failed_registrations: + registration_id = reg_info['registration'] + + try: + registration = Registration.objects.get(_id=registration_id) + + if should_auto_retry(reg_info, registration): + auto_retryable.append(registration) + logger.info(f"Registration {registration_id} eligible for auto-retry") + else: + needs_manual_intervention.append(reg_info) + logger.info(f"Registration {registration_id} needs manual intervention") + + except Registration.DoesNotExist: + logger.warning(f"Registration {registration_id} not found") + needs_manual_intervention.append(reg_info) + continue + + successfully_retried = [] + failed_auto_retries = [] + + for reg in auto_retryable: + try: + logger.info(f"Attempting auto-retry for stuck registration {reg._id}") + + archive( + reg, + permissible_addons=DEFAULT_PERMISSIBLE_ADDONS, + allow_unconfigured=True, + skip_collisions=True + ) + + successfully_retried.append(reg._id) + logger.info(f"Successfully auto-retried registration {reg._id}") + + except Exception as e: + logger.error(f"Auto-retry failed for registration {reg._id}: {e}") + failed_auto_retries.append({ + 'registration': reg._id, + 'auto_retry_error': str(e), + 'original_info': next(info for info in failed_registrations if info['registration'] == reg._id) + }) + + needs_manual_intervention.extend(failed_auto_retries) + + logger.info(f"Auto-retry results: {len(successfully_retried)} successful, {len(failed_auto_retries)} failed") + + summary = { + 'total_failed': len(failed_registrations), + 'auto_retried_success': len(successfully_retried), + 'auto_retried_failed': len(failed_auto_retries), + 'needs_manual': len(needs_manual_intervention), + 'successfully_retried_ids': successfully_retried + } + + logger.info(f"Enhanced audit completed: {summary}") + return summary + + +def should_auto_retry(reg_info, registration): + if not reg_info.get('can_be_reset', False): + return False + + addon_list = reg_info.get('addon_list', []) + complex_addons = set(addon_list) - {'osfstorage', 'wiki'} + if complex_addons: + logger.info(f"Registration {registration._id} has complex addons: {complex_addons}") + return False + + logs_after_reg = reg_info.get('logs_on_original_after_registration_date', []) + if logs_after_reg: + logger.info(f"Registration {registration._id} has post-registration logs: {logs_after_reg}") + return False + + successful_after = reg_info.get('succeeded_registrations_after_failed', []) + if successful_after: + logger.info(f"Registration {registration._id} has successful registrations after failure: {successful_after}") + return False + + import django.utils.timezone as timezone + from datetime import timedelta + if registration.registered_date: + age = timezone.now() - registration.registered_date + if age > timedelta(days=30): + logger.info(f"Registration {registration._id} is too old ({age.days} days)") + return False + return True + +@celery_app.task(name='scripts.manual_restart_approval_batch') +def manual_restart_approval_batch(): + logger.info('Running manual restart approval batch task') + + try: + from scripts.check_manual_restart_approval import check_manual_restart_approvals_batch + result = check_manual_restart_approvals_batch.delay(hours_back=24) + return f"Queued manual restart approval batch task: {result.id}" + except Exception as e: + logger.error(f"Error running manual restart approval batch: {e}") + raise + + +if __name__ == '__main__': + result = enhanced_stuck_registration_audit() + print(f"Audit completed: {result}") \ No newline at end of file diff --git a/scripts/find_spammy_content.py b/scripts/find_spammy_content.py index 2e05328b7d6..eec8c5a3b11 100644 --- a/scripts/find_spammy_content.py +++ b/scripts/find_spammy_content.py @@ -70,7 +70,7 @@ def find_spammy_content(regex, days, model, ban): item_data['fullname'] = item.creator.fullname data.append(item_data) if ban: - item.suspend_spam_user(item.creator) + item.suspend_spam_user(item.creator, self_spam=True) return data def find_spammy_content_fast(regex, days, model, ban): @@ -92,5 +92,5 @@ def find_spammy_content_fast(regex, days, model, ban): item_data['fullname'] = item['creator__fullname'] data.append(item_data) if ban: - model.load(item['guids___id']).suspend_spam_user(item['creator__guids___id']) + model.load(item['guids___id']).suspend_spam_user(item['creator__guids___id'], self_spam=True) return data diff --git a/scripts/generate_sitemap.py b/scripts/generate_sitemap.py index 6039eb56025..7ab62c42a99 100644 --- a/scripts/generate_sitemap.py +++ b/scripts/generate_sitemap.py @@ -19,6 +19,7 @@ from framework.celery_tasks import app as celery_app from django.db.models import Q, F, OuterRef, Subquery from osf.models import OSFUser, AbstractNode, Preprint, PreprintProvider +from osf.models.spam import SpamStatus from osf.utils.workflows import DefaultStates from scripts import utils as script_utils from website import settings @@ -185,7 +186,7 @@ def generate(self): # AbstractNode urls (Nodes and Registrations, no Collections) objs = (AbstractNode.objects .filter(is_public=True, is_deleted=False, retraction_id__isnull=True) - .exclude(type__in=['osf.collection']) + .exclude(type__in=['osf.collection'], spam_status__in=[SpamStatus.SPAM, SpamStatus.FLAGGED]) .values('guids___id', 'modified')) progress.start(objs.count(), 'NODE: ') for obj in objs: @@ -198,8 +199,8 @@ def generate(self): self.log_errors('NODE', obj['guids___id'], e) progress.increment() progress.stop() - #Removed previous logic as it blocked withdrawn preprints to get in sitemap generator - objs = Preprint.objects.filter(date_published__isnull=False).annotate( + objs = Preprint.objects.filter( + date_published__isnull=False).exclude(spam_status__in=[SpamStatus.SPAM, SpamStatus.FLAGGED]).annotate( most_recent_non_withdrawn=Subquery( Preprint.objects.filter( guids=OuterRef('guids') diff --git a/scripts/remove_after_use/populate_notification_subscriptions_node_file_updated.py b/scripts/remove_after_use/populate_notification_subscriptions_node_file_updated.py new file mode 100644 index 00000000000..61625ce6b1f --- /dev/null +++ b/scripts/remove_after_use/populate_notification_subscriptions_node_file_updated.py @@ -0,0 +1,128 @@ +import django +django.setup() + +from website.app import init_app +init_app(routes=False) + +from datetime import datetime +from framework.celery_tasks import app as celery_app +from django.contrib.contenttypes.models import ContentType +from django.db.models import Count, F, OuterRef, Subquery, IntegerField, CharField +from django.db.models.functions import Cast, Coalesce +from osf.models import Node, NotificationSubscription, NotificationTypeEnum + + +@celery_app.task(name='scripts.remove_after_use.populate_notification_subscriptions_node_file_updated') +def populate_notification_subscriptions_node_file_updated(batch_size: int = 1000): + print('---Starting NODE_FILE_UPDATED subscriptions population script----') + global_start = datetime.now() + + node_file_nt = NotificationTypeEnum.NODE_FILE_UPDATED + + node_ct = ContentType.objects.get_for_model(Node) + + node_notifications_sq = ( + NotificationSubscription.objects.filter( + content_type=node_ct, + notification_type=node_file_nt.instance, + object_id=Cast(OuterRef('pk'), CharField()), + ).values( + 'object_id' + ).annotate( + cnt=Count('id') + ).values('cnt')[:1] + ) + + nodes_qs = ( + Node.objects + .filter(is_deleted=False) + .annotate( + contributors_count=Count('_contributors', distinct=True), + notifications_count=Coalesce( + Subquery( + node_notifications_sq, + output_field=IntegerField(), + ), + 0 + ), + ).exclude(contributors_count=F('notifications_count')) + ).iterator(chunk_size=batch_size) + + items_to_create = [] + total_created = 0 + batch_start = datetime.now() + count_nodes = 0 + count_contributors = 0 + for node in nodes_qs: + count_nodes += 1 + for contributor in node.contributors.all(): + count_contributors += 1 + items_to_create.append( + NotificationSubscription( + notification_type=node_file_nt.instance, + user=contributor, + content_type=node_ct, + object_id=node.id, + _is_digest=True, + message_frequency='none', + ) + ) + if len(items_to_create) >= batch_size: + print(f'Creating batch of {len(items_to_create)} subscriptions...') + try: + NotificationSubscription.objects.bulk_create( + items_to_create, + batch_size=batch_size, + ignore_conflicts=True, + ) + total_created += len(items_to_create) + items_to_create = [] + except Exception as exeption: + print(f"Error during bulk_create: {exeption}") + continue + finally: + items_to_create.clear() + batch_end = datetime.now() + print(f'Batch took {batch_end - batch_start}') + + if count_contributors % batch_size == 0: + print(f'Processed {count_nodes} nodes with {count_contributors} contributors, created {total_created} subscriptions') + batch_start = datetime.now() + + if items_to_create: + final_batch_start = datetime.now() + print(f'Creating final batch of {len(items_to_create)} subscriptions...') + try: + NotificationSubscription.objects.bulk_create( + items_to_create, + batch_size=batch_size, + ignore_conflicts=True, + ) + total_created += len(items_to_create) + except Exception as exeption: + print(f"Error during bulk_create: {exeption}") + final_batch_end = datetime.now() + print(f'Final batch took {final_batch_end - final_batch_start}') + + global_end = datetime.now() + print(f'Total time for NODE_FILE_UPDATED subscription population: {global_end - global_start}') + print(f'Created {total_created} subscriptions.') + print('----Creation finished----') + +@celery_app.task(name='scripts.remove_after_use.update_notification_subscriptions_node_file_updated') +def update_notification_subscriptions_node_file_updated(): + print('---Starting NODE_FILE_UPDATED subscriptions update script----') + + node_file_nt = NotificationTypeEnum.NODE_FILE_UPDATED + + updated_start = datetime.now() + updated = ( + NotificationSubscription.objects.filter( + notification_type__name=node_file_nt, + _is_digest=False, + ) + .update(_is_digest=True) + ) + updated_end = datetime.now() + print(f'Updated {updated} subscriptions. Took time: {updated_end - updated_start}') + print('Update finished.') diff --git a/scripts/remove_after_use/populate_notification_subscriptions_user_global_file_updated.py b/scripts/remove_after_use/populate_notification_subscriptions_user_global_file_updated.py new file mode 100644 index 00000000000..651143d6f8a --- /dev/null +++ b/scripts/remove_after_use/populate_notification_subscriptions_user_global_file_updated.py @@ -0,0 +1,111 @@ +import django +django.setup() + +from website.app import init_app +init_app(routes=False) + +from django.utils import timezone +from dateutil.relativedelta import relativedelta +from datetime import datetime +from framework.celery_tasks import app as celery_app +from django.contrib.contenttypes.models import ContentType +from osf.models import OSFUser, NotificationSubscription, NotificationTypeEnum + +@celery_app.task(name='scripts.remove_after_use.populate_notification_subscriptions_user_global_file_updated') +def populate_notification_subscriptions_user_global_file_updated(per_last_years: int | None= None, batch_size: int = 1000): + print('---Starting USER_FILE_UPDATED subscriptions population script----') + global_start = datetime.now() + + user_file_updated_nt = NotificationTypeEnum.USER_FILE_UPDATED + user_ct = ContentType.objects.get_for_model(OSFUser) + if per_last_years: + from_date = timezone.now() - relativedelta(years=per_last_years) + user_qs = (OSFUser.objects + .filter(date_last_login__gte=from_date) + .exclude(subscriptions__notification_type__name=user_file_updated_nt) + .distinct('id') + .order_by('id') + .iterator(chunk_size=batch_size) + ) + else: + user_qs = (OSFUser.objects + .exclude(subscriptions__notification_type__name=user_file_updated_nt) + .distinct('id') + .order_by('id') + .iterator(chunk_size=batch_size) + ) + + items_to_create = [] + total_created = 0 + + batch_start = datetime.now() + for count, user in enumerate(user_qs, 1): + items_to_create.append( + NotificationSubscription( + notification_type=user_file_updated_nt.instance, + user=user, + content_type=user_ct, + object_id=user.id, + _is_digest=True, + message_frequency='none', + ) + ) + if len(items_to_create) >= batch_size: + print(f'Creating batch of {len(items_to_create)} subscriptions...') + try: + NotificationSubscription.objects.bulk_create( + items_to_create, + batch_size=batch_size, + ignore_conflicts=True, + ) + total_created += len(items_to_create) + except Exception as e: + print(f'Error during bulk_create: {e}') + finally: + items_to_create.clear() + batch_end = datetime.now() + print(f'Batch took {batch_end - batch_start}') + + if count % batch_size == 0: + print(f'Processed {count}, created {total_created}') + batch_start = datetime.now() + + if items_to_create: + final_batch_start = datetime.now() + print(f'Creating final batch of {len(items_to_create)} subscriptions...') + try: + NotificationSubscription.objects.bulk_create( + items_to_create, + batch_size=batch_size, + ignore_conflicts=True, + ) + total_created += len(items_to_create) + except Exception as e: + print(f'Error during bulk_create: {e}') + final_batch_end = datetime.now() + print(f'Final batch took {final_batch_end - final_batch_start}') + + global_end = datetime.now() + print(f'Total time for USER_FILE_UPDATED subscription population: {global_end - global_start}') + print(f'Created {total_created} subscriptions.') + print('----Creation finished----') + +@celery_app.task(name='scripts.remove_after_use.update_notification_subscriptions_user_global_file_updated') +def update_notification_subscriptions_user_global_file_updated(): + print('---Starting USER_FILE_UPDATED subscriptions updating script----') + + user_file_updated_nt = NotificationTypeEnum.USER_FILE_UPDATED + + update_start = datetime.now() + updated = ( + NotificationSubscription.objects + .filter( + notification_type__name=user_file_updated_nt, + _is_digest=False, + ) + .update(_is_digest=True) + ) + update_end = datetime.now() + + print(f'Updated {updated} subscriptions. Took time: {update_end - update_start}') + print('Update finished.') diff --git a/scripts/remove_after_use/populate_notification_subscriptions_user_global_reviews.py b/scripts/remove_after_use/populate_notification_subscriptions_user_global_reviews.py new file mode 100644 index 00000000000..edfca287d0d --- /dev/null +++ b/scripts/remove_after_use/populate_notification_subscriptions_user_global_reviews.py @@ -0,0 +1,104 @@ +import django +django.setup() + +from website.app import init_app +init_app(routes=False) + +from django.utils import timezone +from dateutil.relativedelta import relativedelta +from datetime import datetime +from framework.celery_tasks import app as celery_app +from django.contrib.contenttypes.models import ContentType +from osf.models import OSFUser, NotificationSubscription, NotificationTypeEnum + + +@celery_app.task(name='scripts.remove_after_use.populate_notification_subscriptions_user_global_reviews') +def populate_notification_subscriptions_user_global_reviews(per_last_years: int | None = None, batch_size: int = 1000): + print('---Starting REVIEWS_SUBMISSION_STATUS subscriptions population script----') + global_start = datetime.now() + + review_nt = NotificationTypeEnum.REVIEWS_SUBMISSION_STATUS + user_ct = ContentType.objects.get_for_model(OSFUser) + if per_last_years: + from_date = timezone.now() - relativedelta(years=per_last_years) + user_qs = OSFUser.objects.filter(date_last_login__gte=from_date).exclude( + subscriptions__notification_type__name=review_nt.instance + ).distinct('id') + else: + user_qs = OSFUser.objects.exclude( + subscriptions__notification_type__name=review_nt.instance + ).distinct('id') + + items_to_create = [] + total_created = 0 + + batch_start = datetime.now() + for count, user in enumerate(user_qs, 1): + items_to_create.append( + NotificationSubscription( + notification_type=review_nt.instance, + user=user, + content_type=user_ct, + object_id=user.id, + _is_digest=True, + message_frequency='none', + ) + ) + if len(items_to_create) >= batch_size: + print(f'Creating batch of {len(items_to_create)} subscriptions...') + try: + NotificationSubscription.objects.bulk_create( + items_to_create, + batch_size=batch_size, + ignore_conflicts=True, + ) + total_created += len(items_to_create) + except Exception as e: + print(f'Error during bulk_create: {e}') + finally: + items_to_create.clear() + batch_end = datetime.now() + print(f'Batch took {batch_end - batch_start}') + + if count % batch_size == 0: + print(f'Processed {count}, created {total_created}') + batch_start = datetime.now() + + if items_to_create: + final_batch_start = datetime.now() + print(f'Creating final batch of {len(items_to_create)} subscriptions...') + try: + NotificationSubscription.objects.bulk_create( + items_to_create, + batch_size=batch_size, + ignore_conflicts=True, + ) + total_created += len(items_to_create) + except Exception as e: + print(f'Error during bulk_create: {e}') + final_batch_end = datetime.now() + print(f'Final batch took {final_batch_end - final_batch_start}') + + global_end = datetime.now() + print(f'Total time for REVIEWS_SUBMISSION_STATUS subscription population: {global_end - global_start}') + print(f'Created {total_created} subscriptions.') + print('----Creation finished----') + +@celery_app.task(name='scripts.remove_after_use.update_notification_subscriptions_user_global_reviews') +def update_notification_subscriptions_user_global_reviews(): + print('---Starting REVIEWS_SUBMISSION_STATUS subscriptions updating script----') + + review_nt = NotificationTypeEnum.REVIEWS_SUBMISSION_STATUS + + updated_start = datetime.now() + updated = ( + NotificationSubscription.objects.filter( + notification_type__name=review_nt, + _is_digest=False, + ) + .update(_is_digest=True) + ) + updated_end = datetime.now() + + print(f'Updated {updated} subscriptions. Took time: {updated_end - updated_start}') + print('Update finished.') diff --git a/scripts/tests/test_find_spammy_content.py b/scripts/tests/test_find_spammy_content.py index 78056f9cc6b..126161334a0 100644 --- a/scripts/tests/test_find_spammy_content.py +++ b/scripts/tests/test_find_spammy_content.py @@ -32,7 +32,7 @@ def user_two(self): @pytest.fixture def kombat_node(self, user): - return NodeFactory(title='Mortal Kombat Spam', creator=user) + return NodeFactory(title='Mortal Kombat Spam', creator=user, is_public=True) @pytest.fixture def node_two(self, user_two): @@ -47,7 +47,7 @@ def spam_node_but_old(self, user_two): @pytest.fixture def kombat_registration(self, user): - return RegistrationFactory(title='Mortal Kombat Spam', creator=user) + return RegistrationFactory(title='Mortal Kombat Spam', creator=user, is_public=True) @pytest.fixture def registration_two(self, user_two): @@ -55,7 +55,7 @@ def registration_two(self, user_two): @pytest.fixture def kombat_preprint(self, user): - return PreprintFactory(title='Mortal Kombat Spam', creator=user) + return PreprintFactory(title='Mortal Kombat Spam', creator=user, is_public=True) @pytest.fixture def preprint_two(self, user_two): diff --git a/scripts/tests/test_populate_new_and_noteworthy.py b/scripts/tests/test_populate_new_and_noteworthy.py index 13f3536e55c..dbe183930f4 100644 --- a/scripts/tests/test_populate_new_and_noteworthy.py +++ b/scripts/tests/test_populate_new_and_noteworthy.py @@ -7,23 +7,24 @@ from scripts import populate_new_and_noteworthy_projects as script -TEST_NEW_AND_NOTEWORTHY_GUID = 'nguid' +NEW_AND_NOTEWORTHY_LINKS_NODE = 'nguid' +@mock.patch('scripts.populate_new_and_noteworthy_projects.NEW_AND_NOTEWORTHY_LINKS_NODE', NEW_AND_NOTEWORTHY_LINKS_NODE) class TestPopulateNewAndNoteworthy(OsfTestCase): def setUp(self): super().setUp() self.new_and_noteworthy_links_node = ProjectFactory() - self.new_and_noteworthy_links_node._id = TEST_NEW_AND_NOTEWORTHY_GUID + self.new_and_noteworthy_links_node._id = NEW_AND_NOTEWORTHY_LINKS_NODE self.new_and_noteworthy_links_node.save() - self.nn1 = ProjectFactory(is_public=True, title='Noteworthy Alpha') - self.nn2 = ProjectFactory(is_public=True, title='Noteworthy Bravo') - self.nn3 = ProjectFactory(is_public=True, title='Noteworthy Charlie') - self.nn4 = ProjectFactory(is_public=True, title='Noteworthy Foxtrot') - self.nn5 = ProjectFactory(is_public=True, title='Noteworthy Golf') + self.nn1 = ProjectFactory(is_public=True, title='Noteworthy Project Alpha') + self.nn2 = ProjectFactory(is_public=True, title='Noteworthy Project Beta') + self.nn3 = ProjectFactory(is_public=True, title='Noteworthy Project Gamma') + self.nn4 = ProjectFactory(is_public=True, title='Noteworthy Project Delta') + self.nn5 = ProjectFactory(is_public=True, title='Noteworthy Project Epsilon') self.all_ids = {self.nn1._id, self.nn2._id, self.nn3._id, self.nn4._id, self.nn5._id} @@ -35,7 +36,7 @@ def test_get_new_and_noteworthy_nodes(self): new_noteworthy = script.get_new_and_noteworthy_nodes(self.new_and_noteworthy_links_node) assert set(new_noteworthy) == self.all_ids - @mock.patch.object(script, 'NEW_AND_NOTEWORTHY_LINKS_NODE', TEST_NEW_AND_NOTEWORTHY_GUID) + @mock.patch.object(script, 'NEW_AND_NOTEWORTHY_LINKS_NODE', NEW_AND_NOTEWORTHY_LINKS_NODE) def test_populate_new_and_noteworthy(self): assert self.new_and_noteworthy_links_node._nodes.count() == 0 diff --git a/tests/test_addons.py b/tests/test_addons.py index 59aef22bfd3..f1686fbc56d 100644 --- a/tests/test_addons.py +++ b/tests/test_addons.py @@ -30,7 +30,6 @@ from addons.github.tests.factories import GitHubAccountFactory from addons.osfstorage.models import OsfStorageFileNode, OsfStorageFolder, OsfStorageFile from addons.osfstorage.tests.factories import FileVersionFactory -from osf import features from osf.models import files as file_models from osf.models.files import BaseFileNode, TrashedFileNode from osf.utils.permissions import WRITE, READ @@ -43,8 +42,6 @@ from api.caching.utils import storage_usage_cache from dateutil.parser import parse as parse_date from framework import sentry -from website.settings import EXTERNAL_EMBER_APPS -from waffle.testutils import override_flag from django.conf import settings as django_conf_settings SessionStore = import_module(django_conf_settings.SESSION_ENGINE).SessionStore @@ -1333,7 +1330,7 @@ def test_redirects_to_guid(self): ) assert resp.status_code == 302 - assert resp.location == f'/{guid._id}/' + assert resp.location == f'{settings.DOMAIN}{guid._id}/' def test_action_download_redirects_to_download_with_param(self): file_node = self.get_test_file() @@ -1376,40 +1373,6 @@ def test_action_download_redirects_to_download_with_version(self): # Note: version is added but us but all other url params are added as well assert_urls_equal(location.url, file_node.generate_waterbutler_url(action='download', direct=None, revision=1, version='')) - @mock.patch('website.views.stream_emberapp') - @pytest.mark.enable_bookmark_creation - def test_action_view_calls_view_file(self, mock_ember): - self.user.reload() - self.project.reload() - - file_node = self.get_test_file() - guid = file_node.get_guid(create=True) - - with override_flag(features.EMBER_FILE_PROJECT_DETAIL, active=True): - self.app.get(f'/{guid._id}/?action=view', auth=self.user.auth) - - args, kwargs = mock_ember.call_args - assert kwargs == {} - assert args[0] == EXTERNAL_EMBER_APPS['ember_osf_web']['server'] - assert args[1] == EXTERNAL_EMBER_APPS['ember_osf_web']['path'].rstrip('/') - - @mock.patch('website.views.stream_emberapp') - @pytest.mark.enable_bookmark_creation - def test_no_action_calls_view_file(self, mock_ember): - self.user.reload() - self.project.reload() - - file_node = self.get_test_file() - guid = file_node.get_guid(create=True) - - with override_flag(features.EMBER_FILE_PROJECT_DETAIL, active=True): - self.app.get(f'/{guid._id}/', auth=self.user.auth) - - args, kwargs = mock_ember.call_args - assert kwargs == {} - assert args[0] == EXTERNAL_EMBER_APPS['ember_osf_web']['server'] - assert args[1] == EXTERNAL_EMBER_APPS['ember_osf_web']['path'].rstrip('/') - def test_download_create_guid(self): file_node = self.get_test_file() assert file_node.get_guid() is None @@ -1478,30 +1441,19 @@ def test_nonstorage_addons_raise(self): ) assert resp.status_code == 400 - @mock.patch('website.views.stream_emberapp') - def test_head_returns_url_and_redirect(self, mock_ember): + def test_head_returns_url_and_redirect(self): file_node = self.get_test_file() guid = file_node.get_guid(create=True) - with override_flag(features.EMBER_FILE_PROJECT_DETAIL, active=True): - resp = self.app.head(f'/{guid._id}/', auth=self.user.auth) - assert resp.status_code == 200 - - args, kwargs = mock_ember.call_args - assert kwargs == {} - assert args[0] == EXTERNAL_EMBER_APPS['ember_osf_web']['server'] - assert args[1] == EXTERNAL_EMBER_APPS['ember_osf_web']['path'].rstrip('/') - + resp = self.app.head(f'/{guid._id}/', auth=self.user.auth) + assert resp.status_code == 302 def test_head_returns_url_with_version_and_redirect(self): file_node = self.get_test_file() guid = file_node.get_guid(create=True) resp = self.app.head(f'/{guid._id}/?revision=1&foo=bar', auth=self.user.auth) - location = furl(resp.location) - # Note: version is added but us but all other url params are added as well assert resp.status_code == 302 - assert_urls_equal(location.url, file_node.generate_waterbutler_url(direct=None, revision=1, version='', foo='bar')) def test_nonexistent_addons_raise(self): path = 'cloudfiles' @@ -1539,26 +1491,6 @@ def test_unauth_addons_raise(self): self.assertEqual(resp.status_code, 401) assert resp.status_code == 401 - def test_resolve_folder_raise(self): - folder = OsfStorageFolder( - name='folder', - target=self.project, - path='/test/folder/', - materialized_path='/test/folder/', - ) - folder.save() - resp = self.app.get( - self.project.web_url_for( - 'addon_view_or_download_file', - path=folder._id, - provider='osfstorage', - ), - auth=self.user.auth, - - ) - - assert resp.status_code == 400 - def test_delete_action_creates_trashed_file_node(self): file_node = self.get_test_file() payload = { diff --git a/tests/test_auth.py b/tests/test_auth.py index 07e19d7a706..487759603c1 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -90,13 +90,13 @@ def test_confirm_email(self): user.reload() - self.app.set_cookie(settings.COOKIE_NAME, user.get_or_create_cookie().decode()) - res = self.app.get(f'/confirm/{user._id}/{token}') - - res = self.app.resolve_redirect(res) + with capture_notifications(expect_none=True): + self.app.set_cookie(settings.COOKIE_NAME, user.get_or_create_cookie().decode()) + res = self.app.get(f'/confirm/{user._id}/{token}') + res = self.app.resolve_redirect(res) - assert res.status_code == 302 - assert '/' == urlparse(res.location).path + assert res.status_code == 302 + assert '/my-projects/' == urlparse(res.location).path # assert len(get_session()['status']) == 1 def test_get_user_by_id(self): @@ -114,7 +114,7 @@ def test_get_user_with_wrong_password_returns_false(self): assert not auth.get_user(email=user.username, password='wrong') def test_get_user_by_external_info(self): - service_url = 'http://localhost:5000/dashboard/' + service_url = 'http://localhost:5000/my_projects/' user, validated_credentials, cas_resp = generate_external_user_with_resp(service_url) user.save() assert auth.get_user(external_id_provider=validated_credentials['provider'], external_id=validated_credentials['id']) == user @@ -123,7 +123,7 @@ def test_get_user_by_external_info(self): @mock.patch('framework.auth.cas.CasClient.service_validate') def test_successful_external_login_cas_redirect(self, mock_service_validate, mock_get_user_from_cas_resp): # TODO: check in qa url encoding - service_url = 'http://localhost:5000/dashboard/' + service_url = 'http://localhost:5000/my_projects/' user, validated_credentials, cas_resp = generate_external_user_with_resp(service_url) mock_service_validate.return_value = cas_resp mock_get_user_from_cas_resp.return_value = (user, validated_credentials, 'authenticate') @@ -138,7 +138,7 @@ def test_successful_external_login_cas_redirect(self, mock_service_validate, moc @mock.patch('framework.auth.cas.get_user_from_cas_resp') @mock.patch('framework.auth.cas.CasClient.service_validate') def test_successful_external_first_login(self, mock_service_validate, mock_get_user_from_cas_resp): - service_url = 'http://localhost:5000/dashboard/' + service_url = 'http://localhost:5000/my_projects/' _, validated_credentials, cas_resp = generate_external_user_with_resp(service_url, user=False) mock_service_validate.return_value = cas_resp mock_get_user_from_cas_resp.return_value = (None, validated_credentials, 'external_first_login') @@ -151,7 +151,7 @@ def test_successful_external_first_login(self, mock_service_validate, mock_get_u @mock.patch('framework.auth.cas.get_user_from_cas_resp') @mock.patch('framework.auth.cas.CasClient.service_validate') def test_successful_external_first_login_without_attributes(self, mock_service_validate, mock_get_user_from_cas_resp, mock_external_first_login_authenticate): - service_url = 'http://localhost:5000/dashboard/' + service_url = 'http://localhost:5000/my_projects/' user, validated_credentials, cas_resp = generate_external_user_with_resp(service_url, user=False, release=False) mock_service_validate.return_value = cas_resp mock_get_user_from_cas_resp.return_value = (None, validated_credentials, 'external_first_login') diff --git a/tests/test_auth_basic_auth.py b/tests/test_auth_basic_auth.py index bad44316bfa..e1b9d6e5b8d 100644 --- a/tests/test_auth_basic_auth.py +++ b/tests/test_auth_basic_auth.py @@ -99,4 +99,4 @@ def test_expired_cookie(self): self.app.set_cookie(settings.COOKIE_NAME, str(cookie)) res = self.app.get(self.reachable_url) assert res.status_code == 302 - assert '/' == res.location + assert '/login/' == res.location diff --git a/tests/test_auth_views.py b/tests/test_auth_views.py index 608edc06519..7b24e286c15 100644 --- a/tests/test_auth_views.py +++ b/tests/test_auth_views.py @@ -558,25 +558,25 @@ def test_osf_login_with_auth(self): # login: user with auth data = login_and_register_handler(self.auth) assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == web_url_for('dashboard', _absolute=True) + assert data.get('next_url') == web_url_for('my_projects', _absolute=True) def test_osf_login_without_auth(self): # login: user without auth data = login_and_register_handler(self.no_auth) assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == web_url_for('dashboard', _absolute=True) + assert data.get('next_url') == web_url_for('my_projects', _absolute=True) def test_osf_register_with_auth(self): # register: user with auth data = login_and_register_handler(self.auth, login=False) assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == web_url_for('dashboard', _absolute=True) + assert data.get('next_url') == web_url_for('my_projects', _absolute=True) def test_osf_register_without_auth(self): # register: user without auth data = login_and_register_handler(self.no_auth, login=False) assert data.get('status_code') == http_status.HTTP_200_OK - assert data.get('next_url') == web_url_for('dashboard', _absolute=True) + assert data.get('next_url') == web_url_for('my_projects', _absolute=True) def test_next_url_login_with_auth(self): # next_url login: user with auth @@ -610,13 +610,13 @@ def test_institution_login_with_auth(self): # institution login: user with auth data = login_and_register_handler(self.auth, campaign='institution') assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == web_url_for('dashboard', _absolute=True) + assert data.get('next_url') == web_url_for('my_projects', _absolute=True) def test_institution_login_without_auth(self): # institution login: user without auth data = login_and_register_handler(self.no_auth, campaign='institution') assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == cas.get_login_url(web_url_for('dashboard', _absolute=True), + assert data.get('next_url') == cas.get_login_url(web_url_for('my_projects', _absolute=True), campaign='institution') def test_institution_login_next_url_with_auth(self): @@ -635,13 +635,13 @@ def test_institution_register_with_auth(self): # institution register: user with auth data = login_and_register_handler(self.auth, login=False, campaign='institution') assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == web_url_for('dashboard', _absolute=True) + assert data.get('next_url') == web_url_for('my_projects', _absolute=True) def test_institution_register_without_auth(self): # institution register: user without auth data = login_and_register_handler(self.no_auth, login=False, campaign='institution') assert data.get('status_code') == http_status.HTTP_302_FOUND - assert data.get('next_url') == cas.get_login_url(web_url_for('dashboard', _absolute=True), campaign='institution') + assert data.get('next_url') == cas.get_login_url(web_url_for('my_projects', _absolute=True), campaign='institution') def test_campaign_login_with_auth(self): for campaign in get_campaigns(): @@ -782,7 +782,7 @@ def setUp(self): super().setUp() self.goodbye_url = web_url_for('goodbye', _absolute=True) self.redirect_url = web_url_for('forgot_password_get', _absolute=True) - self.valid_next_url = web_url_for('dashboard', _absolute=True) + self.valid_next_url = web_url_for('my_projects', _absolute=True) self.invalid_next_url = 'http://localhost:1234/abcde' self.auth_user = AuthUserFactory() diff --git a/tests/test_campaigns.py b/tests/test_campaigns.py index 1df6a32169a..221ce03f8cf 100644 --- a/tests/test_campaigns.py +++ b/tests/test_campaigns.py @@ -238,7 +238,7 @@ def setUp(self): super().setUp() self.url_login = web_url_for('auth_login', campaign='institution') self.url_register = web_url_for('auth_register', campaign='institution') - self.service_url = web_url_for('dashboard', _absolute=True) + self.service_url = web_url_for('my_projects', _absolute=True) # go to CAS institution login page if not logged in def test_institution_not_logged_in(self): diff --git a/tests/test_comfirmation_view_block_bing.py b/tests/test_comfirmation_view_block_bing.py index 8ef5290b6e3..bfb207272aa 100644 --- a/tests/test_comfirmation_view_block_bing.py +++ b/tests/test_comfirmation_view_block_bing.py @@ -152,7 +152,7 @@ def test_external_login_confirm_email_get_create_user(self): create_url = user.get_confirmation_url( user.username, external_id_provider='service', - destination='dashboard' + destination='my_projects' ) res = self.app.get( @@ -179,7 +179,7 @@ def test_external_login_confirm_email_get_link_user(self): link_url = user.get_confirmation_url( user.username, external_id_provider='service', - destination='dashboard' + destination='my_projects' ) res = self.app.get( diff --git a/tests/test_ember_osf_web.py b/tests/test_ember_osf_web.py deleted file mode 100644 index 31868132fb7..00000000000 --- a/tests/test_ember_osf_web.py +++ /dev/null @@ -1,59 +0,0 @@ -from unittest import mock -from flask import request - -from tests.base import OsfTestCase -from website.ember_osf_web.decorators import ember_flag_is_active -from osf_tests.factories import FlagFactory, UserFactory - -from django.contrib.auth.models import Group - - -class TestEmberFlagIsActive(OsfTestCase): - - def setUp(self): - super().setUp() - self.flag = FlagFactory(name='active_flag') - FlagFactory(name='inactive_flag', everyone=False).save() - self.mock_func = lambda: 'test value' - - @mock.patch('website.ember_osf_web.decorators.use_ember_app') - def test_use_ember_app(self, mock_use_ember_app): - ember_flag_is_active('active_flag')(self.mock_func)() - - mock_use_ember_app.assert_called_with() - - @mock.patch('website.ember_osf_web.decorators.use_ember_app') - def test_dont_use_ember_app(self, mock_use_ember_app): - # mock over external module 'waffle.flag_is_active` not ours - - ember_flag_is_active('inactive_flag')(self.mock_func)() - - assert not mock_use_ember_app.called - - @mock.patch('api.waffle.utils._get_current_user') - @mock.patch('website.ember_osf_web.decorators.flag_is_active') - @mock.patch('website.ember_osf_web.decorators.use_ember_app') - def test_ember_flag_is_active_authenticated_user(self, mock_use_ember_app, mock_flag_is_active, mock__get_current_user): - # mock over external module 'waffle.flag_is_active` not ours - - user = UserFactory() - mock__get_current_user.return_value = user - - ember_flag_is_active('active_flag')(self.mock_func)() - - mock_flag_is_active.assert_called_with(request, 'active_flag') - mock_use_ember_app.assert_called_with() - - @mock.patch('api.waffle.utils._get_current_user', return_value=None) - @mock.patch('website.ember_osf_web.decorators.flag_is_active') - @mock.patch('website.ember_osf_web.decorators.use_ember_app') - def test_ember_flag_is_active_unauthenticated_user(self, mock_use_ember_app, mock_flag_is_active, mock__get_current_user): - # mock over external module 'waffle.flag_is_active` not ours - - ember_flag_is_active('active_flag')(self.mock_func)() - group = Group.objects.create(name='foo') - - self.flag.groups.add(group) - - mock_flag_is_active.assert_called_with(request, 'active_flag') - mock_use_ember_app.assert_called_with() diff --git a/tests/test_misc_views.py b/tests/test_misc_views.py index 3d30905ab31..3d1e0cad47c 100644 --- a/tests/test_misc_views.py +++ b/tests/test_misc_views.py @@ -390,7 +390,7 @@ def test_external_login_email_get_with_invalid_session(self): def test_external_login_confirm_email_get_with_another_user_logged_in(self): # TODO: check in qa url encoding another_user = AuthUserFactory() - url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='dashboard') + url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='my_projects') res = self.app.get(url, auth=another_user.auth) assert res.status_code == 302, 'redirects to cas logout' assert '/logout?service=' in res.location @@ -404,7 +404,7 @@ def test_external_login_confirm_email_get_without_destination(self): def test_external_login_confirm_email_get_create(self): # TODO: check in qa url encoding assert not self.user.is_registered - url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='dashboard') + url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='my_projects') res = self.app.get(url) assert res.status_code == 302, 'redirects to cas login' assert '/login?service=' in res.location @@ -419,7 +419,7 @@ def test_external_login_confirm_email_get_link(self): self.user.external_identity['orcid'][self.provider_id] = 'LINK' self.user.save() assert not self.user.is_registered - url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='dashboard') + url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='my_projects') with capture_notifications() as notifications: res = self.app.get(url) assert len(notifications['emits']) == 1 @@ -437,7 +437,7 @@ def test_external_login_confirm_email_get_link(self): def test_external_login_confirm_email_get_duped_id(self): dupe_user = UserFactory(external_identity={'orcid': {self.provider_id: 'CREATE'}}) assert dupe_user.external_identity == self.user.external_identity - url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='dashboard') + url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='my_projects') res = self.app.get(url) assert res.status_code == 302, 'redirects to cas login' assert 'You should be redirected automatically' in str(res.html) @@ -451,7 +451,7 @@ def test_external_login_confirm_email_get_duped_id(self): def test_external_login_confirm_email_get_duping_id(self): dupe_user = UserFactory(external_identity={'orcid': {self.provider_id: 'VERIFIED'}}) - url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='dashboard') + url = self.user.get_confirmation_url(self.user.username, external_id_provider='orcid', destination='my_projects') res = self.app.get(url) assert res.status_code == 403, 'only allows one user to link an id' @@ -766,28 +766,10 @@ def test_find_unread_includes_edited_comments(self): n_unread = Comment.find_n_unread(user=user, node=project, page='node') assert n_unread == 1 -@mock.patch('website.views.PROXY_EMBER_APPS', False) class TestResolveGuid(OsfTestCase): def setUp(self): super().setUp() - @mock.patch('website.views.use_ember_app') - def test_preprint_provider_without_domain(self, mock_use_ember_app): - provider = PreprintProviderFactory(domain='') - preprint = PreprintFactory(provider=provider) - url = web_url_for('resolve_guid', _guid=True, guid=preprint._id) - res = self.app.get(url) - mock_use_ember_app.assert_called_with() - - @mock.patch('website.views.use_ember_app') - def test_preprint_provider_with_domain_without_redirect(self, mock_use_ember_app): - domain = 'https://test.com/' - provider = PreprintProviderFactory(_id='test', domain=domain, domain_redirect_enabled=False) - preprint = PreprintFactory(provider=provider) - url = web_url_for('resolve_guid', _guid=True, guid=preprint._id) - res = self.app.get(url) - mock_use_ember_app.assert_called_with() - def test_preprint_provider_with_domain_with_redirect(self): domain = 'https://test.com/' provider = PreprintProviderFactory(_id='test', domain=domain, domain_redirect_enabled=True) @@ -799,11 +781,3 @@ def test_preprint_provider_with_domain_with_redirect(self): assert res.status_code == 301 assert res.headers['location'] == f'{domain}{preprint._id}/' assert res.request.path == f'/{preprint._id}/' - - @mock.patch('website.views.use_ember_app') - def test_preprint_provider_with_osf_domain(self, mock_use_ember_app): - provider = PreprintProviderFactory(_id='osf', domain='https://osf.io/') - preprint = PreprintFactory(provider=provider) - url = web_url_for('resolve_guid', _guid=True, guid=preprint._id) - res = self.app.get(url) - mock_use_ember_app.assert_called_with() diff --git a/tests/test_preprints.py b/tests/test_preprints.py index e14d8920487..7d669ee3e3f 100644 --- a/tests/test_preprints.py +++ b/tests/test_preprints.py @@ -2770,17 +2770,3 @@ def test_date_created_first_version_with_rejected_v1(self, creator, moderator): assert v2.date_created_first_version != v2_created assert v1.date_created_first_version == v1_created - - -class TestEmberRedirect(OsfTestCase): - - def test_ember_redirect_to_versioned_guid(self): - pp = PreprintFactory(filename='test.pdf', finish=True) - res = self.app.get(f'preprints/provider/{pp.get_guid()._id}/') - guid_with_version = pp._id - assert res.status_code == 302 - assert res.location.endswith(f'{guid_with_version}') - guid_with_no_version = guid_with_version.split('_')[0] - location_with_no_guid = res.location.replace(guid_with_version, '') - # check if location has not wrong format https://osf.io/preprints/socarxiv/3rhyz/3rhyz_v1 - assert location_with_no_guid == location_with_no_guid.replace(guid_with_no_version, '') diff --git a/tests/test_project_contributor_views.py b/tests/test_project_contributor_views.py index 9bfd98870d5..c03cf9365b3 100644 --- a/tests/test_project_contributor_views.py +++ b/tests/test_project_contributor_views.py @@ -432,7 +432,7 @@ def test_multiple_project_remove_contributor(self): self.project.reload() self.project2.reload() assert self.user2._id not in self.project.contributors - assert '/dashboard/' not in res.json + assert '/my_projects/' not in res.json assert self.user2._id not in self.project2.contributors # A log event was added @@ -453,7 +453,7 @@ def test_private_project_remove_self_not_admin(self): ) self.project.reload() assert res.status_code == 200 - assert res.json['redirectUrl'] == '/dashboard/' + assert res.json['redirectUrl'] == '/my-projects/' assert self.user2._id not in self.project.contributors def test_public_project_remove_self_not_admin(self): diff --git a/tests/test_project_views.py b/tests/test_project_views.py index 9403546e0dd..f4456feb18c 100644 --- a/tests/test_project_views.py +++ b/tests/test_project_views.py @@ -435,7 +435,7 @@ def test_retraction_view(self): assert registration.title in res.text assert res.status_code == 200 - for route in ['files', 'wiki/home', 'contributors', 'settings', 'withdraw', 'register', 'register/fakeid']: + for route in ['files', 'contributors', 'settings', 'withdraw', 'register', 'register/fakeid']: res = self.app.get(f'{url}{route}/', auth=self.auth) assert res.status_code == 302, route res = self.app.get(f'{url}{route}/', auth=self.auth, follow_redirects=True) diff --git a/tests/test_registrations/test_views.py b/tests/test_registrations/test_views.py index 3fe1f518e4f..15d0e60cc77 100644 --- a/tests/test_registrations/test_views.py +++ b/tests/test_registrations/test_views.py @@ -166,31 +166,6 @@ def test_get_draft_registrations_only_gets_drafts_for_that_node(self): for draft in res.json['drafts']: assert draft['pk'] in [f._id for f in found] - def test_new_draft_registration_POST(self): - target = NodeFactory(creator=self.user) - payload = { - 'schema_name': self.meta_schema.name, - 'schema_version': self.meta_schema.schema_version - } - url = target.web_url_for('new_draft_registration') - - with capture_notifications(): - res = self.app.post(url, data=payload, auth=self.user.auth) - assert res.status_code == http_status.HTTP_302_FOUND - target.reload() - draft = DraftRegistration.objects.get(branched_from=target) - assert draft.registration_schema == self.meta_schema - - def test_new_draft_registration_on_registration(self): - target = RegistrationFactory(user=self.user) - payload = { - 'schema_name': self.meta_schema.name, - 'schema_version': self.meta_schema.schema_version - } - url = target.web_url_for('new_draft_registration') - res = self.app.post(url, json=payload, auth=self.user.auth) - assert res.status_code == http_status.HTTP_403_FORBIDDEN - def test_update_draft_registration_cant_update_registered(self): metadata = { 'summary': {'value': 'updated'} @@ -207,12 +182,6 @@ def test_update_draft_registration_cant_update_registered(self): res = self.app.put(url, json=payload, auth=self.user.auth) assert res.status_code == http_status.HTTP_403_FORBIDDEN - def test_edit_draft_registration_page_already_registered(self): - self.draft.register(self.auth, save=True) - url = self.node.web_url_for('edit_draft_registration_page', draft_id=self.draft._id) - res = self.app.get(url, auth=self.user.auth) - assert res.status_code == http_status.HTTP_403_FORBIDDEN - def test_update_draft_registration(self): metadata = { 'summary': { diff --git a/tests/test_webtests.py b/tests/test_webtests.py index cf0ea89c579..64c5669f3e9 100644 --- a/tests/test_webtests.py +++ b/tests/test_webtests.py @@ -79,7 +79,7 @@ def test_can_see_profile_url(self): res = self.app.get(self.user.url, follow_redirects=True) assert self.user.url in res.text - # `GET /login/` without parameters is redirected to `/dashboard/` page which has `@must_be_logged_in` decorator + # `GET /login/` without parameters is redirected to `/my-projects/` page which has `@must_be_logged_in` decorator # if user is not logged in, she/he is further redirected to CAS login page def test_is_redirected_to_cas_if_not_logged_in_at_login_page(self): res = self.app.resolve_redirect(self.app.get('/login/')) @@ -87,26 +87,26 @@ def test_is_redirected_to_cas_if_not_logged_in_at_login_page(self): location = res.headers.get('Location') assert 'login?service=' in location - def test_is_redirected_to_dashboard_if_already_logged_in_at_login_page(self): + def test_is_redirected_to_myprojects_if_already_logged_in_at_login_page(self): res = self.app.get('/login/', auth=self.user.auth) assert res.status_code == 302 - assert 'dashboard' in res.headers.get('Location') + assert 'my-projects' in res.headers.get('Location') def test_register_page(self): res = self.app.get('/register/') assert res.status_code == 200 - def test_is_redirected_to_dashboard_if_already_logged_in_at_register_page(self): + def test_is_redirected_to_myprojects_if_already_logged_in_at_register_page(self): res = self.app.get('/register/', auth=self.user.auth) assert res.status_code == 302 - assert 'dashboard' in res.headers.get('Location') + assert 'my-projects' in res.headers.get('Location') def test_sees_projects_in_her_dashboard(self): # the user already has a project project = ProjectFactory(creator=self.user) project.add_contributor(self.user) project.save() - res = self.app.get('/myprojects/', auth=self.user.auth) + res = self.app.get('/my-projects/', auth=self.user.auth) assert 'Projects' in res.text # Projects heading def test_does_not_see_osffiles_in_user_addon_settings(self): @@ -124,7 +124,7 @@ def test_sees_osffiles_in_project_addon_settings(self): def test_sees_correct_title_on_dashboard(self): # User goes to dashboard - res = self.app.get('/myprojects/', auth=self.auth, follow_redirects=True) + res = self.app.get('/my-projects/', auth=self.auth, follow_redirects=True) title = res.html.title.string assert 'OSF | My Projects' == title @@ -179,32 +179,6 @@ def test_sees_logs_on_a_project(self): # Can see log event assert 'created' in res.text - def test_no_wiki_content_message(self): - project = ProjectFactory(creator=self.user) - # Goes to project's wiki, where there is no content - res = self.app.get(f'/{project._primary_key}/wiki/home/', auth=self.auth) - # Sees a message indicating no content - assert 'Add important information, links, or images here to describe your project.' in res.text - # Sees that edit panel is open by default when home wiki has no content - assert 'panelsUsed: ["view", "menu", "edit"]' in res.text - - def test_wiki_content(self): - project = ProjectFactory(creator=self.user) - wiki_page_name = 'home' - wiki_content = 'Kittens' - wiki_page = WikiFactory( - user=self.user, - node=project, - ) - WikiVersionFactory( - wiki_page=wiki_page, - content=wiki_content - ) - res = self.app.get(f'/{project._primary_key}/wiki/{wiki_page_name}/', auth=self.auth) - assert 'Add important information, links, or images here to describe your project.' not in res.text - assert wiki_content in res.text - assert 'panelsUsed: ["view", "menu"]' in res.text - def test_wiki_page_name_non_ascii(self): project = ProjectFactory(creator=self.user) non_ascii = to_mongo_key('WöRlÐé') @@ -221,11 +195,6 @@ def test_noncontributor_cannot_see_wiki_if_no_content(self): # Should not see wiki widget (since non-contributor and no content) assert 'Add important information, links, or images here to describe your project.' not in res.text - def test_wiki_does_not_exist(self): - project = ProjectFactory(creator=self.user) - res = self.app.get(f'/{project._primary_key}/wiki/not a real page yet/', auth=self.auth) - assert 'Add important information, links, or images here to describe your project.' in res.text - def test_sees_own_profile(self): res = self.app.get('/profile/', auth=self.auth) td1 = res.html.find('td', text=re.compile(r'Public(.*?)Profile')) diff --git a/webpack.common.config.js b/webpack.common.config.js index dea1f7abdc9..e76b755dbdf 100644 --- a/webpack.common.config.js +++ b/webpack.common.config.js @@ -26,14 +26,12 @@ var entry = { 'base-page': staticPath('js/pages/base-page.js'), 'dashboard-page': staticPath('js/pages/dashboard-page.js'), 'profile-page': staticPath('js/pages/profile-page.js'), - 'project-dashboard': staticPath('js/pages/project-dashboard-page.js'), 'project-base-page': staticPath('js/pages/project-base-page.js'), 'project-settings-page': staticPath('js/pages/project-settings-page.js'), 'project-addons-page': staticPath('js/pages/project-addons-page.js'), 'registration-retraction-page': staticPath('js/pages/registration-retraction-page.js'), 'registration-edit-page': staticPath('js/pages/registration-edit-page.js'), 'register-page': staticPath('js/pages/register-page.js'), - 'wiki-edit-page': staticPath('js/pages/wiki-edit-page.js'), 'request-access-page': staticPath('js/pages/request-access-page.js'), 'file-page': staticPath('js/pages/file-page.js'), 'files-page': staticPath('js/pages/files-page.js'), @@ -131,7 +129,7 @@ var resolve = { './website/static/vendor/bower_components', 'node_modules', ], - extensions: ['*', '.es6.js', '.js', '.min.js'], + extensions: ['*', '.js', '.min.js'], // Need to alias libraries that aren't managed by bower or npm alias: { 'knockout-sortable': staticPath('vendor/knockout-sortable/knockout-sortable.js'), @@ -206,7 +204,6 @@ module.exports = { output: output, module: { rules: [ - {test: /\.es6\.js$/, exclude: [/node_modules/, /bower_components/, /vendor/], loader: 'babel-loader'}, {test: /\.css$/, use: [{loader: 'style-loader'}, {loader: 'css-loader'}]}, // url-loader uses DataUrls; files-loader emits files {test: /\.png$/, loader: 'url-loader?limit=100000&mimetype=image/png'}, diff --git a/website/archiver/tasks.py b/website/archiver/tasks.py index 6b8436b9523..197b41b886b 100644 --- a/website/archiver/tasks.py +++ b/website/archiver/tasks.py @@ -7,6 +7,9 @@ import celery from celery.utils.log import get_task_logger +from django.utils import timezone +from datetime import timedelta + from framework.celery_tasks import app as celery_app from framework.celery_tasks.utils import logged from framework.exceptions import HTTPError @@ -29,9 +32,13 @@ from website.archiver.utils import normalize_unicode_filenames from website.archiver import signals as archiver_signals +from scripts.check_manual_restart_approval import delayed_manual_restart_approval + from website.project import signals as project_signals from website import settings from website.app import init_addons + +from osf.models.admin_log_entry import AdminLogEntry, MANUAL_ARCHIVE_RESTART from osf.models import ( ArchiveJob, AbstractNode, @@ -370,9 +377,23 @@ def archive_success(self, dst_pk, job_pk): job.save() dst.sanction.ask(dst.get_active_contributors_recursive(unique_users=True)) + if was_manually_restarted(dst): + logger.info(f'Registration {dst._id} was manually restarted, scheduling approval check') + delayed_manual_restart_approval.delay(dst._id, delay_minutes=5) + dst.update_search() +def was_manually_restarted(registration): + recent_logs = AdminLogEntry.objects.filter( + object_id=registration.pk, + action_flag=MANUAL_ARCHIVE_RESTART, + action_time__gte=timezone.now() - timedelta(hours=48) + ) + + return recent_logs.exists() + + @celery_app.task(bind=True) def force_archive(self, registration_id, permissible_addons, allow_unconfigured=False, skip_collisions=False, delete_collisions=False): from osf.management.commands.force_archive import archive, verify diff --git a/website/conferences/views.py b/website/conferences/views.py index 913c991cda9..14038134cb2 100644 --- a/website/conferences/views.py +++ b/website/conferences/views.py @@ -8,12 +8,10 @@ from framework.exceptions import HTTPError from framework.flask import redirect from framework.transactions.handlers import no_auto_transaction -from osf import features from osf.models import AbstractNode, Node, Conference, OSFUser from website import settings from website.conferences import utils from website.conferences.message import ConferenceMessage, ConferenceError -from website.ember_osf_web.decorators import ember_flag_is_active from website.util import web_url_for from website.util.metrics import CampaignSourceTags @@ -209,7 +207,6 @@ def serialize_conference(conf): 'talk': conf.talk, } -@ember_flag_is_active(features.EMBER_MEETING_DETAIL) def conference_results(meeting): """Return the data for the grid view for a conference. :param str meeting: Endpoint name for a conference. @@ -240,7 +237,6 @@ def conference_submissions(**kwargs): """ return {'success': True} -@ember_flag_is_active(features.EMBER_MEETINGS) def conference_view(**kwargs): meetings = [] for conf in Conference.objects.all(): diff --git a/website/ember_osf_web/__init__.py b/website/ember_osf_web/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/website/ember_osf_web/decorators.py b/website/ember_osf_web/decorators.py deleted file mode 100644 index 6b939312ee2..00000000000 --- a/website/ember_osf_web/decorators.py +++ /dev/null @@ -1,22 +0,0 @@ -import functools - -from flask import request - -from api.waffle.utils import flag_is_active -from website.ember_osf_web.views import use_ember_app - - -def ember_flag_is_active(flag_name): - """ - Decorator for checking whether ember flag is active. If so, proxy to ember - app; otherwise, load old view. - """ - def decorator(func): - @functools.wraps(func) - def wrapped(*args, **kwargs): - if flag_is_active(request, flag_name): - return use_ember_app() - else: - return func(*args, **kwargs) - return wrapped - return decorator diff --git a/website/ember_osf_web/views.py b/website/ember_osf_web/views.py deleted file mode 100644 index 84f23ad8327..00000000000 --- a/website/ember_osf_web/views.py +++ /dev/null @@ -1,26 +0,0 @@ -import os -import json -from website import settings -from framework.status import pop_status_messages - -from website.settings import EXTERNAL_EMBER_APPS - -ember_osf_web_dir = os.path.abspath(os.path.join(os.getcwd(), EXTERNAL_EMBER_APPS['ember_osf_web']['path'])) - -routes = [ - '/institutions/', -] - -def use_ember_app(**kwargs): - from website.views import stream_emberapp - resp = stream_emberapp(EXTERNAL_EMBER_APPS['ember_osf_web']['server'], ember_osf_web_dir) - messages = pop_status_messages() - if messages: - try: - status = [{'id': stat[5] if stat[5] else stat[0], 'class': stat[2], 'jumbo': stat[1], 'dismiss': stat[3], 'extra': stat[6]} for stat in messages] - resp.set_cookie(settings.COOKIE_NAME + '_status', json.dumps(status)) - except IndexError: - # Ignoring the error as it will only occur when statuses were created prior to merging the changes that add - # extra and id, (patch to prevent breaking the app meanwhile) - pass - return resp diff --git a/website/institutions/__init__.py b/website/institutions/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/website/institutions/views.py b/website/institutions/views.py deleted file mode 100644 index 9477fa8c910..00000000000 --- a/website/institutions/views.py +++ /dev/null @@ -1,7 +0,0 @@ -from website.ember_osf_web.views import use_ember_app - -def view_institution(inst_id, **kwargs): - return use_ember_app() - -def view_institution_dashboard(inst_id, **kwargs): - return use_ember_app() diff --git a/website/preprints/views.py b/website/preprints/views.py index e27da1e7f1f..d42a19b48ae 100644 --- a/website/preprints/views.py +++ b/website/preprints/views.py @@ -1,8 +1,5 @@ from framework.flask import redirect # VOL-aware redirect -def preprint_landing_page(**kwargs): - return {} - def preprint_redirect(**kwargs): return redirect('/preprints/') diff --git a/website/profile/views.py b/website/profile/views.py index 37572b00366..a08a586742e 100644 --- a/website/profile/views.py +++ b/website/profile/views.py @@ -25,14 +25,12 @@ from framework.status import push_status_message from framework.utils import throttle_period_expired -from osf import features from osf.models import ApiOAuth2Application, ApiOAuth2PersonalToken, OSFUser, NotificationTypeEnum from osf.exceptions import BlockedEmailError, OSFError from osf.utils.requests import string_type_request_headers from website import mailchimp_utils from website import settings from website import language -from website.ember_osf_web.decorators import ember_flag_is_active from website.oauth.utils import get_available_scopes from website.profile import utils as profile_utils from website.util import api_v2_url, web_url_for, paths @@ -253,7 +251,6 @@ def profile_view_id_json(uid, auth): return _profile_view(user, is_profile) @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_PROFILE) def profile_view(auth): # Embed node data, so profile node lists can be rendered return _profile_view(auth.user, True, include_node_counts=True) @@ -268,7 +265,6 @@ def profile_view_id(uid, auth): @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS) def user_profile(auth, **kwargs): user = auth.user return { @@ -278,7 +274,6 @@ def user_profile(auth, **kwargs): @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_ACCOUNTS) def user_account(auth, **kwargs): user = auth.user user_addons = addon_utils.get_addons_by_config_type('user', user) @@ -297,7 +292,6 @@ def user_account(auth, **kwargs): @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_ACCOUNTS) def user_account_password(auth, **kwargs): user = auth.user old_password = request.form.get('old_password', None) @@ -336,7 +330,6 @@ def user_account_password(auth, **kwargs): @must_be_logged_in -@ember_flag_is_active(features.ENABLE_GV) def user_addons(auth, **kwargs): user = auth.user @@ -354,7 +347,6 @@ def user_addons(auth, **kwargs): return ret @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_NOTIFICATIONS) def user_notifications(auth, **kwargs): """Get subscribe data from user""" return { @@ -362,7 +354,6 @@ def user_notifications(auth, **kwargs): } @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_APPS) def oauth_application_list(auth, **kwargs): """Return app creation page with list of known apps. API is responsible for tying list to current user.""" app_list_url = api_v2_url('applications/') @@ -371,7 +362,6 @@ def oauth_application_list(auth, **kwargs): } @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_APPS) def oauth_application_register(auth, **kwargs): """Register an API application: blank form view""" app_list_url = api_v2_url('applications/') # POST request to this url @@ -379,7 +369,6 @@ def oauth_application_register(auth, **kwargs): 'app_detail_url': ''} @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_APPS) def oauth_application_detail(auth, **kwargs): """Show detail for a single OAuth application""" client_id = kwargs.get('client_id') @@ -401,7 +390,6 @@ def oauth_application_detail(auth, **kwargs): 'app_detail_url': app_detail_url} @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_TOKENS) def personal_access_token_list(auth, **kwargs): """Return token creation page with list of known tokens. API is responsible for tying list to current user.""" token_list_url = api_v2_url('tokens/') @@ -410,7 +398,6 @@ def personal_access_token_list(auth, **kwargs): } @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_TOKENS) def personal_access_token_register(auth, **kwargs): """Register a personal access token: blank form view""" token_list_url = api_v2_url('tokens/') # POST request to this url @@ -419,7 +406,6 @@ def personal_access_token_register(auth, **kwargs): 'scope_options': get_available_scopes()} @must_be_logged_in -@ember_flag_is_active(features.EMBER_USER_SETTINGS_TOKENS) def personal_access_token_detail(auth, **kwargs): """Show detail for a single personal access token""" _id = kwargs.get('_id') diff --git a/website/project/metadata/utils.py b/website/project/metadata/utils.py index e094da63753..de2bfb82f6a 100644 --- a/website/project/metadata/utils.py +++ b/website/project/metadata/utils.py @@ -39,7 +39,6 @@ def serialize_draft_registration(draft, auth=None): 'updated': utils.iso8601format(draft.datetime_updated), 'flags': draft.flags, 'urls': { - 'edit': node.web_url_for('edit_draft_registration_page', draft_id=draft._id, _guid=True), 'before_register': node.api_url_for('project_before_register'), 'register': absolute_reverse('nodes:node-registrations', kwargs={'node_id': node._id, 'version': 'v2'}), 'register_page': node.web_url_for('draft_before_register_page', draft_id=draft._id, _guid=True), diff --git a/website/project/views/contributor.py b/website/project/views/contributor.py index 1e2edc1cefe..9ad43fa0304 100644 --- a/website/project/views/contributor.py +++ b/website/project/views/contributor.py @@ -321,7 +321,7 @@ def project_manage_contributors(auth, node, **kwargs): raise HTTPError(http_status.HTTP_409_CONFLICT, data={'message_long': error.args[0]}) # If user has removed herself from project, alert; redirect to - # node summary if node is public, else to user's dashboard page + # node summary if node is public, else to user's my_projects page if not node.is_contributor_or_group_member(auth.user): status.push_status_message( 'You have removed yourself as a contributor from this project', @@ -330,7 +330,7 @@ def project_manage_contributors(auth, node, **kwargs): ) if node.is_public: return {'redirectUrl': node.url} - return {'redirectUrl': web_url_for('dashboard')} + return {'redirectUrl': web_url_for('my_projects')} # Else if user has revoked her admin permissions, alert and stay on # current page if not node.has_permission(auth.user, ADMIN): @@ -385,7 +385,7 @@ def project_remove_contributor(auth, **kwargs): 'message_long': 'Could not remove contributor.'}) # On parent node, if user has removed herself from project, alert; redirect to - # node summary if node is public, else to user's dashboard page + # node summary if node is public, else to user's my_projects page if not node.is_contributor_or_group_member(auth.user) and node_id == parent_id: status.push_status_message( 'You have removed yourself as a contributor from this project', @@ -396,7 +396,7 @@ def project_remove_contributor(auth, **kwargs): if node.is_public: redirect_url = {'redirectUrl': node.url} else: - redirect_url = {'redirectUrl': web_url_for('dashboard')} + redirect_url = {'redirectUrl': web_url_for('my_projects')} if node.is_public: node.update_search() diff --git a/website/project/views/drafts.py b/website/project/views/drafts.py index e4ee762c992..e4ecd1bc92a 100644 --- a/website/project/views/drafts.py +++ b/website/project/views/drafts.py @@ -7,13 +7,12 @@ from dateutil.parser import parse as parse_date from django.utils import timezone -from flask import request, redirect +from flask import request import pytz from framework.database import autoload from framework.exceptions import HTTPError -from osf import features from osf.utils.sanitize import strip_html from osf.utils.permissions import ADMIN from osf.utils.functional import rapply @@ -25,9 +24,7 @@ must_have_permission, ) from website import settings -from website.ember_osf_web.decorators import ember_flag_is_active -from website.project import utils from website.project.metadata.schemas import METASCHEMA_ORDERING from website.project.metadata.utils import serialize_meta_schema, serialize_draft_registration from website.project.utils import serialize_node @@ -150,60 +147,6 @@ def get_draft_registrations(auth, node, *args, **kwargs): 'drafts': sorted_serialized_drafts }, http_status.HTTP_200_OK -@must_have_permission(ADMIN) -@must_be_valid_project -@must_be_contributor_and_not_group_member -@ember_flag_is_active(features.EMBER_CREATE_DRAFT_REGISTRATION) -def new_draft_registration(auth, node, *args, **kwargs): - """Create a new draft registration for the node - - :return: Redirect to the new draft's edit page - :rtype: flask.redirect - :raises: HTTPError - """ - if node.is_registration: - raise HTTPError(http_status.HTTP_403_FORBIDDEN, data={ - 'message_short': "Can't create draft", - 'message_long': 'Creating draft registrations on registered projects is not allowed.' - }) - data = request.values - - schema_name = data.get('schema_name') - if not schema_name: - raise HTTPError( - http_status.HTTP_400_BAD_REQUEST, - data={ - 'message_short': 'Must specify a schema_name', - 'message_long': 'Please specify a schema_name' - } - ) - - schema_version = data.get('schema_version', 2) - - meta_schema = get_schema_or_fail(schema_name, int(schema_version)) - draft = DraftRegistration.create_from_node( - node=node, - user=auth.user, - schema=meta_schema, - data={} - ) - return redirect(node.web_url_for('edit_draft_registration_page', draft_id=draft._id, _guid=True)) - - -@must_have_permission(ADMIN) -@must_be_contributor_and_not_group_member -@ember_flag_is_active(features.EMBER_EDIT_DRAFT_REGISTRATION) -@must_be_branched_from_node -def edit_draft_registration_page(auth, node, draft, **kwargs): - """Draft registration editor - - :return: serialized DraftRegistration - :rtype: dict - """ - check_draft_state(draft) - ret = utils.serialize_node(node, auth, primary=True) - ret['draft'] = serialize_draft_registration(draft, auth) - return ret @must_have_permission(ADMIN) @must_be_contributor_and_not_group_member diff --git a/website/project/views/file.py b/website/project/views/file.py index 780b26a740c..393782d47ef 100644 --- a/website/project/views/file.py +++ b/website/project/views/file.py @@ -4,13 +4,11 @@ from flask import request from osf import features -from osf.models import Node, Registration from api.waffle.utils import flag_is_active from website.util import rubeus from website.project.decorators import must_be_contributor_or_public, must_not_be_retracted_registration from website.project.views.node import _view_project -from website.ember_osf_web.views import use_ember_app @must_not_be_retracted_registration @@ -19,11 +17,6 @@ def collect_file_trees(auth, node, **kwargs): """Collect file trees for all add-ons implementing HGrid views, then format data as appropriate. """ - if isinstance(node, Node) and flag_is_active(request, features.EMBER_PROJECT_FILES): - return use_ember_app() - - if isinstance(node, Registration) and flag_is_active(request, features.EMBER_REGISTRATION_FILES): - return use_ember_app() serialized = _view_project(node, auth, primary=True) # Add addon static assets diff --git a/website/project/views/node.py b/website/project/views/node.py index c07a1377086..94e4a63fe47 100644 --- a/website/project/views/node.py +++ b/website/project/views/node.py @@ -18,7 +18,6 @@ from framework.auth.decorators import must_be_logged_in, collect_auth from osf.external.gravy_valet.request_helpers import get_gv_citation_url_list_for_project from osf.external.gravy_valet.translations import EphemeralAddonConfig -from website.ember_osf_web.decorators import ember_flag_is_active from api.waffle.utils import flag_is_active, storage_i18n_flag_active, storage_usage_flag_active from framework.exceptions import HTTPError from osf.models.nodelog import NodeLog @@ -31,7 +30,6 @@ from website import language from website.util import rubeus -from website.ember_osf_web.views import use_ember_app from osf.exceptions import NodeStateError from website.project import new_node, new_private_link from website.project.decorators import ( @@ -269,7 +267,6 @@ def project_before_template(auth, node, **kwargs): def node_registrations(auth, node, **kwargs): if request.path.startswith('/project/'): return redirect(f'/{node._id}/registrations/') - return use_ember_app() @must_be_valid_project @@ -278,18 +275,13 @@ def node_registrations(auth, node, **kwargs): def node_forks(auth, node, **kwargs): if request.path.startswith('/project/'): return redirect('/' + node._id + '/forks/') - return use_ember_app() @must_be_valid_project @must_not_be_retracted_registration @must_be_logged_in @must_have_permission(READ) -@ember_flag_is_active(features.EMBER_PROJECT_SETTINGS) def node_setting(auth, node, **kwargs): - if node.is_registration and flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): - # Registration settings page obviated during redesign - return redirect(node.url) auth.user.update_affiliated_institutions_by_email_domain() auth.user.save() ret = _view_project(node, auth, primary=True) @@ -324,7 +316,6 @@ def node_setting(auth, node, **kwargs): @must_not_be_registration @must_be_logged_in @must_have_permission(WRITE) -@ember_flag_is_active(features.ENABLE_GV) def node_addons(auth, node, **kwargs): ret = _view_project(node, auth, primary=True) @@ -410,7 +401,6 @@ def node_choose_addons(auth, node, **kwargs): @must_be_valid_project @must_not_be_retracted_registration @must_have_permission(READ) -@ember_flag_is_active(features.EMBER_PROJECT_CONTRIBUTORS) def node_contributors(auth, node, **kwargs): ret = _view_project(node, auth, primary=True) ret['contributors'] = utils.serialize_contributors(node.contributors, node) @@ -458,7 +448,6 @@ def make_citation_widget_data(addon_name: str): @process_token_or_pass @must_be_valid_project(retractions_valid=True) @must_be_contributor_or_public -@ember_flag_is_active(features.EMBER_PROJECT_DETAIL) def view_project(auth, node, **kwargs): primary = '/api/v1' not in request.path ret = _view_project(node, auth, @@ -576,7 +565,6 @@ def project_reorder_components(node, **kwargs): def project_statistics(auth, node, **kwargs): if request.path.startswith('/project/'): return redirect('/' + node._id + '/analytics/') - return use_ember_app() ############################################################################### @@ -654,7 +642,7 @@ def component_remove(auth, node, **kwargs): if parent and parent.can_view(auth): redirect_url = node.parent_node.url else: - redirect_url = '/dashboard/' + redirect_url = '/my_projects/' return { 'url': redirect_url, diff --git a/website/project/views/register.py b/website/project/views/register.py index 265fda1edea..6d8fe5a293f 100644 --- a/website/project/views/register.py +++ b/website/project/views/register.py @@ -15,19 +15,16 @@ must_not_be_registration, must_not_be_retracted_registration ) -from osf import features from osf.models import Identifier, RegistrationSchema from website.project.utils import serialize_node from osf.utils.permissions import ADMIN from website import language -from website.ember_osf_web.decorators import ember_flag_is_active from website.project.metadata.schemas import _id_to_name from website import util from website.project.metadata.utils import serialize_meta_schema from website.project.model import has_anonymous_link from .node import _view_project -from api.waffle.utils import flag_is_active @must_be_valid_project @must_not_be_retracted_registration @@ -117,11 +114,7 @@ def node_registration_retraction_post(auth, node, **kwargs): @must_be_valid_project @must_not_be_retracted_registration @must_be_contributor_or_public -@ember_flag_is_active(features.EMBER_REGISTRATION_FORM_DETAIL) def node_register_template_page(auth, node, metaschema_id, **kwargs): - if flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): - # Registration meta page obviated during redesign - return redirect(node.url) if node.is_registration and bool(node.registered_schema): try: meta_schema = RegistrationSchema.objects.get(_id=metaschema_id) diff --git a/website/registries/views.py b/website/registries/views.py index c7307fe626f..4fc631553c2 100644 --- a/website/registries/views.py +++ b/website/registries/views.py @@ -19,16 +19,7 @@ def draft_registrations(auth, **kwargs): 'initiator': { 'name': draft.initiator.fullname, }, - 'url': draft.branched_from.web_url_for( - 'edit_draft_registration_page', - draft_id=draft._id, - ), } for draft in drafts ], } - - -def registries_landing_page(**kwargs): - # placeholder for developer who don't have ember app set up. - return {} diff --git a/website/reviews/views.py b/website/reviews/views.py deleted file mode 100644 index bbb97564245..00000000000 --- a/website/reviews/views.py +++ /dev/null @@ -1,2 +0,0 @@ -def reviews_landing_page(**kwargs): - return {} diff --git a/website/routes.py b/website/routes.py index 7110aaa7e77..226f03fb1f1 100644 --- a/website/routes.py +++ b/website/routes.py @@ -1,7 +1,5 @@ import os from rest_framework import status as http_status -import requests -from urllib.parse import urljoin import json import waffle @@ -9,8 +7,6 @@ from flask import request from flask import send_from_directory -from flask import Response -from flask import stream_with_context from flask import g from django.conf import settings as api_settings from django.utils.encoding import smart_str @@ -30,7 +26,7 @@ from framework.auth.core import _get_current_user from osf import features -from osf.models import Institution, Preprint +from osf.models import Institution from osf.utils import sanitize from osf.utils import permissions from website import util @@ -54,12 +50,8 @@ from website.policies import views as policy_views from website.preprints import views as preprint_views from website.registries import views as registries_views -from website.reviews import views as reviews_views -from website.institutions import views as institution_views -from website.ember_osf_web import views as ember_osf_web_views from website.closed_challenges import views as closed_challenges_views from website.identifiers import views as identifier_views -from website.settings import EXTERNAL_EMBER_APPS, EXTERNAL_EMBER_SERVER_TIMEOUT from api.waffle.utils import flag_is_active @@ -236,58 +228,9 @@ def sitemap_file(path): mimetype=mime ) -def ember_app(path=None): - """Serve the contents of the ember application""" - ember_app_folder = None - fp = path or 'index.html' - - ember_app = None - - for k in EXTERNAL_EMBER_APPS.keys(): - if request.path.strip('/').startswith(k): - ember_app = EXTERNAL_EMBER_APPS[k] - if k == 'preprints': - # If a valid guid is provided w/o version, find and redirect to the latest version. This only applies - # to route preprints//: e.g. /preprints/osf/abcde -> /preprints/osf/abcde_v3 - if path: - path_values = path.split('/') - guid_str = path_values[1] if len(path_values) > 1 else None - if guid_str: - preprint = Preprint.load(guid_str) - if preprint and preprint._id != guid_str: - return redirect(f"{settings.DOMAIN}preprints/{path_values[0]}/{preprint._id}", code=302) - # For all other cases, let ember app handle it - ember_app = EXTERNAL_EMBER_APPS.get('ember_osf_web', False) or ember_app - break - - if not ember_app: - raise HTTPError(http_status.HTTP_404_NOT_FOUND) - - if settings.PROXY_EMBER_APPS: - path = request.path[len(ember_app['path']):] - url = urljoin(ember_app['server'], path) - resp = requests.get(url, stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT, headers={'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'}) - excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection'] - headers = [(name, value) for (name, value) in resp.raw.headers.items() if name.lower() not in excluded_headers] - return Response(resp.content, resp.status_code, headers) - - ember_app_folder = os.path.abspath(os.path.join(os.getcwd(), ember_app['path'])) - - if not ember_app_folder: - raise HTTPError(http_status.HTTP_404_NOT_FOUND) - - if not os.path.abspath(os.path.join(ember_app_folder, fp)).startswith(ember_app_folder): - # Prevent accessing files outside of the ember build dir - raise HTTPError(http_status.HTTP_404_NOT_FOUND) - - if not os.path.isfile(os.path.join(ember_app_folder, fp)): - fp = 'index.html' - - return send_from_directory(ember_app_folder, fp) - def goodbye(): # Redirect to dashboard if logged in - redirect_url = util.web_url_for('index') + redirect_url = util.web_url_for('auth_login') if _get_current_user(): return redirect(redirect_url) else: @@ -347,70 +290,17 @@ def make_url_map(app): Rule('/sitemaps/', 'get', sitemap_file, json_renderer), ]) - # Ember Applications - if settings.USE_EXTERNAL_EMBER: - # Routes that serve up the Ember application. Hide behind feature flag. - for prefix in EXTERNAL_EMBER_APPS.keys(): - process_rules(app, [ - Rule( - [ - '///download', - '///download/', - ], - ['get', 'post', 'put', 'patch', 'delete'], - website_views.resolve_guid_download, - notemplate, - endpoint_suffix='__' + prefix - ), - ], prefix='/' + prefix) - - process_rules(app, [ - Rule( - [ - '/', - '/', - ], - 'get', - ember_app, - json_renderer, - endpoint_suffix='__' + prefix - ), - ], prefix='/' + prefix) - - if EXTERNAL_EMBER_APPS.get('ember_osf_web'): - process_rules(app, [ - Rule( - ember_osf_web_views.routes, - 'get', - ember_osf_web_views.use_ember_app, - notemplate - ) - ]) - if 'routes' in EXTERNAL_EMBER_APPS['ember_osf_web']: - for route in EXTERNAL_EMBER_APPS['ember_osf_web']['routes']: - process_rules(app, [ - Rule( - [ - '/', - '/', - ], - 'get', - ember_osf_web_views.use_ember_app, - notemplate, - endpoint_suffix='__' + route - ) - ], prefix='/' + route) - ### Base ### process_rules(app, [ - + Rule('/', 'get', website_views.index, notemplate), Rule( '/dashboard/', 'get', website_views.dashboard, notemplate ), + Rule( '/metadata//', 'get', @@ -418,7 +308,7 @@ def make_url_map(app): notemplate ), Rule( - '/myprojects/', + '/my-projects/', 'get', website_views.my_projects, OsfWebRenderer('my_projects.mako', trust=False) @@ -519,26 +409,6 @@ def make_url_map(app): closed_challenges_views.erpc_landing_page, OsfWebRenderer('erpc_landing_page.mako', trust=False) ), - Rule( - '/preprints/', - 'get', - preprint_views.preprint_landing_page, - OsfWebRenderer('public/pages/preprint_landing.mako', trust=False), - ), - - Rule( - '/registries/', - 'get', - registries_views.registries_landing_page, - OsfWebRenderer('public/pages/registries_landing.mako', trust=False), - ), - - Rule( - '/reviews/', - 'get', - reviews_views.reviews_landing_page, - OsfWebRenderer('public/pages/reviews_landing.mako', trust=False), - ), Rule( '/preprint/', @@ -1115,28 +985,9 @@ def make_url_map(app): ], prefix='/api/v1') - # Institution - - process_rules(app, [ - Rule('/institutions//', 'get', institution_views.view_institution, notemplate) - ]) - - process_rules(app, [ - Rule([ - '/institutions//dashboard/', - ], - 'get', - institution_views.view_institution_dashboard, - notemplate) - ]) - - # Project - # Web process_rules(app, [ - Rule('/', 'get', website_views.index, notemplate), - Rule('/goodbye/', 'get', goodbye, notemplate), Rule( @@ -1203,17 +1054,6 @@ def make_url_map(app): OsfWebRenderer('project/settings.mako', trust=False) ), - # Permissions - Rule( # TODO: Where, if anywhere, is this route used? - [ - '/project//permissions//', - '/project//node//permissions//', - ], - 'post', - project_views.node.project_set_privacy, - OsfWebRenderer('project/project.mako', trust=False) - ), - # View forks Rule( [ @@ -1254,22 +1094,6 @@ def make_url_map(app): project_views.node.node_registrations, notemplate, ), - Rule( - [ - '/project//registrations/', - '/project//node//registrations/', - ], - 'post', - project_views.drafts.new_draft_registration, - OsfWebRenderer('project/edit_draft_registration.mako', trust=False)), - Rule( - [ - '/project//drafts//', - '/project//node//drafts//', - ], - 'get', - project_views.drafts.edit_draft_registration_page, - OsfWebRenderer('project/edit_draft_registration.mako', trust=False)), Rule( [ '/project//drafts//register/', @@ -1776,8 +1600,3 @@ def addon_static(addon, filename): @app.route('/assets/') def provider_static(filename): return send_from_directory(directory=provider_static_path, path=filename) - - @app.route('/ember-cli-live-reload.js') - def ember_cli_live_reload(): - req = requests.get(f'{settings.LIVE_RELOAD_DOMAIN}/ember-cli-live-reload.js', stream=True) - return Response(stream_with_context(req.iter_content()), content_type=req.headers['content-type']) diff --git a/website/search/views.py b/website/search/views.py index e774d52532e..828cd0e5661 100644 --- a/website/search/views.py +++ b/website/search/views.py @@ -12,11 +12,9 @@ from framework import sentry from framework.utils import sanitize_html from website import language -from osf import features from osf.models import OSFUser, AbstractNode from website import settings from website.project.views.contributor import get_node_contributors_abbrev -from website.ember_osf_web.decorators import ember_flag_is_active from website.search import exceptions import website.search.search as search from website.search.util import build_query @@ -73,7 +71,6 @@ def search_search(**kwargs): results['time'] = round(time.time() - tick, 2) return results -@ember_flag_is_active(features.EMBER_SEARCH_PAGE) def search_view(): return {'shareUrl': settings.SHARE_URL}, diff --git a/website/settings/defaults.py b/website/settings/defaults.py index 4e0b31c2b16..ec16f334c8e 100644 --- a/website/settings/defaults.py +++ b/website/settings/defaults.py @@ -96,12 +96,6 @@ def parent_dir(path): 'prefix': PROTOCOL, 'suffix': '/' } -# External Ember App Local Development -USE_EXTERNAL_EMBER = False -PROXY_EMBER_APPS = False -# http://docs.python-requests.org/en/master/user/advanced/#timeouts -EXTERNAL_EMBER_SERVER_TIMEOUT = 3.05 -EXTERNAL_EMBER_APPS = {} LOG_PATH = os.path.join(APP_PATH, 'logs') TEMPLATES_PATH = os.path.join(BASE_PATH, 'templates') @@ -439,6 +433,9 @@ class CeleryConfig: 'scripts.populate_new_and_noteworthy_projects', 'website.search.elastic_search', 'scripts.generate_sitemap', + 'scripts.remove_after_use.populate_notification_subscriptions_node_file_updated', + 'scripts.remove_after_use.populate_notification_subscriptions_user_global_file_updated', + 'scripts.remove_after_use.populate_notification_subscriptions_user_global_reviews', 'osf.management.commands.clear_expired_sessions', 'osf.management.commands.delete_withdrawn_or_failed_registration_files', 'osf.management.commands.migrate_pagecounter_data', @@ -478,6 +475,8 @@ class CeleryConfig: 'scripts.add_missing_identifiers_to_preprints', 'osf.management.commands.approve_pending_schema_response', 'api.share.utils', + 'scripts.check_manual_restart_approval', + 'scripts.enhanced_stuck_registration_audit', } try: @@ -568,6 +567,9 @@ class CeleryConfig: 'scripts.approve_embargo_terminations', 'scripts.triggered_mails', 'scripts.generate_sitemap', + 'scripts.remove_after_use.populate_notification_subscriptions_node_file_updated', + 'scripts.remove_after_use.populate_notification_subscriptions_user_global_file_updated', + 'scripts.remove_after_use.populate_notification_subscriptions_user_global_reviews', 'scripts.premigrate_created_modified', 'scripts.add_missing_identifiers_to_preprints', 'osf.management.commands.clear_expired_sessions', @@ -579,6 +581,7 @@ class CeleryConfig: 'osf.management.commands.approve_pending_schema_responses', 'osf.management.commands.sync_doi_metadata', 'api.providers.tasks', + 'api.users.tasks', 'osf.management.commands.daily_reporters_go', 'osf.management.commands.monthly_reporters_go', 'osf.external.spam.tasks', diff --git a/website/settings/local-ci.py b/website/settings/local-ci.py index b1754ef0191..a4d250a9792 100644 --- a/website/settings/local-ci.py +++ b/website/settings/local-ci.py @@ -23,21 +23,6 @@ 'prefix': 'http://local.', 'suffix': ':4201/' } -USE_EXTERNAL_EMBER = True -EXTERNAL_EMBER_APPS = { - 'ember_osf_web': { - 'server': 'http://localhost:4200', - 'path': os.environ.get('HOME') + 'website/ember_osf_web/' - }, - 'preprints': { - 'server': 'http://localhost:4201', - 'path': os.environ.get('HOME') + '/preprints/' - }, - 'registries': { - 'server': 'http://localhost:4202/', - 'path': os.environ.get('HOME') + '/registries/' - } -} SEARCH_ENGINE = 'elastic' diff --git a/website/settings/local-dist.py b/website/settings/local-dist.py index 0c8af5b24eb..01d26b420c2 100644 --- a/website/settings/local-dist.py +++ b/website/settings/local-dist.py @@ -30,29 +30,6 @@ 'prefix': 'http://local.', 'suffix': ':4201/' } -USE_EXTERNAL_EMBER = True -PROXY_EMBER_APPS = True -EMBER_DOMAIN = environ.get('EMBER_DOMAIN', 'localhost') -LIVE_RELOAD_DOMAIN = f'http://{EMBER_DOMAIN}:4200' # Change port for the current app -EXTERNAL_EMBER_APPS = { - 'ember_osf_web': { - 'server': f'http://{EMBER_DOMAIN}:4200/', - 'path': '/ember_osf_web/', - 'routes': [ - 'collections', - 'registries', - 'handbook', - ], - }, - 'preprints': { - 'server': f'http://{EMBER_DOMAIN}:4201/', - 'path': '/preprints/' - }, - 'reviews': { - 'server': f'http://{EMBER_DOMAIN}:4203/', - 'path': '/reviews/' - }, -} SEARCH_ENGINE = 'elastic' ELASTIC_TIMEOUT = 10 diff --git a/website/static/js/comment.js b/website/static/js/comment.js index fed0eea6da5..733b0d067c7 100644 --- a/website/static/js/comment.js +++ b/website/static/js/comment.js @@ -12,7 +12,6 @@ require('jquery-autosize'); var osfHelpers = require('js/osfHelpers'); var CommentPane = require('js/commentpane'); -var markdown = require('js/markdown'); var atMention = require('js/atMention'); // Cached contributor and group member data, to prevent multiple fetches for @mentions @@ -461,11 +460,11 @@ var CommentModel = function(data, $parent, $root) { }); var linkifyOpts = { target: function (href, type) { return type === 'url' ? '_top' : null; } }; - self.contentDisplay = ko.observable(linkifyHtml(markdown.full.render(self.content()), linkifyOpts)); + self.contentDisplay = ko.observable(linkifyHtml(self.content(), linkifyOpts)); - // Update contentDisplay with rendered markdown whenever content changes + // Update contentDisplay with linkified text whenever content changes self.content.subscribe(function(newContent) { - self.contentDisplay(linkifyHtml(markdown.full.render(newContent), linkifyOpts)); + self.contentDisplay(linkifyHtml(newContent, linkifyOpts)); }); self.prettyDateCreated = ko.computed(function() { diff --git a/website/static/js/markdown.js b/website/static/js/markdown.js deleted file mode 100644 index b1dc91d9ffe..00000000000 --- a/website/static/js/markdown.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; -var hljs = require('highlight.js'); -require('highlight-css'); -var MarkdownIt = require('markdown-it'); - -var $ = require('jquery'); -var $osf = require('js/osfHelpers'); -var insDel = require('markdown-it-ins-del'); -var pymarkdownList = require('js/markdown-it-pymarkdown-lists'); - -var highlighter = function (str, lang) { - if (lang && hljs.getLanguage(lang)) { - try { - return hljs.highlight(lang, str).value; - } catch (__) {} - } - - try { - return hljs.highlightAuto(str).value; - } catch (__) {} - - return ''; // use external default escaping - }; - -/** - * Apply .table class (from Bootstrap) to all tables - */ -var bootstrapTable = function(md) { - md.renderer.rules.table_open = function() { return ''; }; -}; - -var oldMarkdownList = function(md) { - md.block.ruler.after('hr', 'pyMarkdownList', pymarkdownList); -}; - -var WATERBUTLER_REGEX = new RegExp(window.contextVars.waterbutlerURL + 'v1\/resources\/[a-zA-Z0-9]{1,}\/providers\/[a-z0-9]{1,}\/'); - -var viewOnlyImage = function(md) { - var defaultRenderer = md.renderer.rules.image; - md.renderer.rules.image = function (tokens, idx, options, env, self) { - var token = tokens[idx]; - var imageLink = token.attrs[token.attrIndex('src')][1]; - if (imageLink.match(WATERBUTLER_REGEX) && $osf.urlParams().view_only) { - token = tokens[idx]; - imageLink = token.attrs[token.attrIndex('src')][1]; - token.attrs[token.attrIndex('src')][1] = imageLink + '&view_only=' + $osf.urlParams().view_only; - tokens[idx] = token; - } - return defaultRenderer(tokens, idx, options, env, self); - }; -}; - -var mfrURL = window.contextVars.node.urls.mfr; -var osfURL = window.contextVars.osfURL; - -var getMfrUrl = function (guid) { - var mfrLink = mfrURL + 'render?url='+ osfURL + guid + '/download/?action=download%26mode=render'; - if ($osf.urlParams().view_only) { - mfrLink += '%26view_only=' + $osf.urlParams().view_only; - } - return mfrLink; -}; - -var mfrId = 0; - -// Full markdown renderer for views / wiki pages / pauses between typing -var markdown = new MarkdownIt('commonmark', { - highlight: highlighter, - linkify: true - }).use(require('@centerforopenscience/markdown-it-atrules'), { - type: 'osf', - pattern: /^http(?:s?):\/\/(?:www\.)?[a-zA-Z0-9 .:]{1,}\/render\?url=http(?:s?):\/\/[a-zA-Z0-9 .:]{1,}\/([a-zA-Z0-9]{1,})\/\?action=download|(^[a-zA-Z0-9]{1,}$)/, - format: function(assetID) { - var id = '__markdown-it-atrules-' + mfrId++; - return '
' + - ''; - } - }) - .use(require('@centerforopenscience/markdown-it-video')) - .use(require('@centerforopenscience/markdown-it-toc')) - .use(require('markdown-it-sanitizer')) - .use(viewOnlyImage) - .use(require('@centerforopenscience/markdown-it-imsize')) - .use(insDel) - .enable('table') - .enable('linkify') - .use(bootstrapTable) - .disable('strikethrough'); - - -// Fast markdown renderer for active editing to prevent slow loading/rendering tasks -var markdownQuick = new MarkdownIt('commonmark', { linkify: true }) - .use(require('markdown-it-sanitizer')) - .use(viewOnlyImage) - .use(require('@centerforopenscience/markdown-it-imsize')) - .disable('link') - .disable('image') - .use(insDel) - .enable('table') - .enable('linkify') - .use(bootstrapTable) - .disable('strikethrough'); - -// Markdown renderer for older wikis rendered before switch date -var markdownOld = new MarkdownIt('commonmark', { linkify: true}) - .use(require('markdown-it-sanitizer')) - .use(require('@centerforopenscience/markdown-it-imsize')) - .use(insDel) - .enable('table') - .enable('linkify') - .use(bootstrapTable) - .use(oldMarkdownList) - .disable('strikethrough'); - -module.exports = { - full: markdown, - quick: markdownQuick, - old: markdownOld -}; diff --git a/website/static/js/myProjects.js b/website/static/js/myProjects.js index 830df968276..148f71d5865 100644 --- a/website/static/js/myProjects.js +++ b/website/static/js/myProjects.js @@ -574,7 +574,7 @@ var MyProjects = { */ self.setFilterHistory = function(index) { // if not on the myprojects version of this page, don't change state (e.g., institutions) - if (window.location.href.indexOf('/myprojects') === -1 ) { + if (window.location.href.indexOf('/my-projects') === -1 ) { return; } var filter; @@ -585,7 +585,7 @@ var MyProjects = { } // Uses replaceState instead of pushState because back buttons will not reset the filter on back without forcing a page refresh // A bug in history causes titles not to change despite setting them here. - window.history.replaceState({setFilter: index}, 'OSF | ' + filter.title, '/myprojects/' + filter.name); + window.history.replaceState({setFilter: index}, 'OSF | ' + filter.title, '/my-projects/' + filter.name); }; /** @@ -593,7 +593,7 @@ var MyProjects = { */ self.getFilterIndex = function() { // if not on the myprojects version of this page, don't change state (e.g., institutions) - if (window.location.href.indexOf('/myprojects') === -1 ) { + if (window.location.href.indexOf('/my-projects') === -1 ) { return 0; } // Cast to string undefined => "undefined" to handle upper/lower case anchors diff --git a/website/static/js/pages/project-dashboard-page.js b/website/static/js/pages/project-dashboard-page.js deleted file mode 100644 index 04cf9ffe5e2..00000000000 --- a/website/static/js/pages/project-dashboard-page.js +++ /dev/null @@ -1,470 +0,0 @@ -/** Initialization code for the project overview page. */ -'use strict'; - -var $ = require('jquery'); -require('jquery-tagsinput'); -require('bootstrap-editable'); -require('js/osfToggleHeight'); - -var m = require('mithril'); -var Fangorn = require('js/fangorn').Fangorn; -var Raven = require('raven-js'); -require('truncate'); - -var $osf = require('js/osfHelpers'); -var LogFeed = require('js/components/logFeed'); -var pointers = require('js/pointers'); -var Comment = require('js/comment'); //jshint ignore:line -var NodeControl = require('js/nodeControl'); -var CitationList = require('js/citationList'); -var CitationWidget = require('js/citationWidget'); -var mathrender = require('js/mathrender'); -var md = require('js/markdown').full; -var oldMd = require('js/markdown').old; -var AddProject = require('js/addProjectPlugin'); -var SocialShare = require('js/components/socialshare'); - -var ctx = window.contextVars; -var node = window.contextVars.node; -var nodeApiUrl = ctx.node.urls.api; -var nodeCategories = ctx.nodeCategories || []; -var currentUserRequestState = ctx.currentUserRequestState; -const tracker = require('js/components/tracker'); - -// Listen for the nodeLoad event (prevents multiple requests for data) -$('body').on('nodeLoad', function(event, data) { - if (!data.node.is_retracted) { - // Initialize controller for "Add Links" modal - new pointers.PointerManager('#addPointer', window.contextVars.node.title); - } - // Initialize CitationWidget if user isn't viewing through an anonymized VOL - if (!data.node.anonymous && !data.node.is_retracted) { - new CitationList('#citationList'); - new CitationWidget('#citationStyleInput', '#citationText'); - } - - if (data.node.identifiers.doi) { - tracker.trackView(data.node.identifiers.doi); - } - - // Initialize nodeControl - new NodeControl.NodeControl('#projectScope', data, {categories: nodeCategories, currentUserRequestState: currentUserRequestState}); - - // Enable the otherActionsButton once the page is loaded so the menu is properly populated - $('#otherActionsButton').removeClass('disabled'); -}); - -// Initialize comment pane w/ its viewmodel -var $comments = $('.comments'); -if ($comments.length) { - var options = { - nodeId : window.contextVars.node.id, - nodeApiUrl: window.contextVars.node.urls.api, - isRegistration: window.contextVars.node.isRegistration, - page: 'node', - rootId: window.contextVars.node.id, - fileId: null, - canComment: window.contextVars.currentUser.canComment, - currentUser: window.contextVars.currentUser, - pageTitle: window.contextVars.node.title, - inputSelector: '.atwho-input' - }; - Comment.init('#commentsLink', '.comment-pane', options); -} -var institutionLogos = { - controller: function(args){ - var self = this; - self.institutions = args.institutions; - self.nLogos = self.institutions.length; - self.side = self.nLogos > 1 ? (self.nLogos === 2 ? '50px' : '35px') : '75px'; - self.width = self.nLogos > 1 ? (self.nLogos === 2 ? '115px' : '86px') : '75px'; - self.makeLogo = function(institution){ - return m('a', {href: '/institutions/' + institution.id}, - m('img', { - height: self.side, width: self.side, - style: {margin: '3px'}, - title: institution.name, - src: institution.logo_path - }) - ); - }; - }, - view: function(ctrl, args){ - var tooltips = function(){ - $('[data-toggle="tooltip"]').tooltip(); - }; - var instCircles = $.map(ctrl.institutions, ctrl.makeLogo); - if (instCircles.length > 4){ - instCircles[3] = m('.fa.fa-plus-square-o', { - style: {margin: '6px', fontSize: '250%', verticalAlign: 'middle'}, - }); - instCircles.splice(4); - } - - return m('', {style: {float: 'left', width: ctrl.width, textAlign: 'center', marginRight: '10px'}, config: tooltips}, instCircles); - } -}; - - -$(document).ready(function () { - // activate bootstrap popovers - $('[data-toggle="popover"]').popover(); - // Allows dropdown elements to persist after being clicked - // Used for the "Share" button in the more actions menu - $('.dropdown').on('click', 'li', function (evt) { - var target = $(evt.target); - // If the clicked element has .keep-open, don't allow the event to propagate - return !(target.hasClass('keep-open') || target.parents('.keep-open').length); - }); - var collectionsActionsURL = $osf.apiV2Url('collection_submission_actions/'); - - $('.collections-retry-icon').on('click', function (evt) { - var target = $(evt.target); - var payload = { - data: { - type: 'collection-submission-actions', - attributes: { - comment: 'Resubmitted via project overview page', - trigger: 'resubmit', - }, - relationships: { - target: { - data: { - id: evt.target.getAttribute('node_id') + '-' + evt.target.getAttribute('collection_id'), - type: 'collection-submission', - } - } - } - } - }; - - var request = $osf.ajaxJSON( - 'POST', - collectionsActionsURL, - { - data: payload, - isCors: true - } - ); - request.done(function(resp) { - location.reload(); - }); - }); - $('.collections-cancel-icon').on('click', function (evt) { - var target = $(evt.target); - var payload = { - data: { - type: 'collection-submission-actions', - attributes: { - comment: 'Canceled via project overview page', - trigger: 'cancel', - }, - relationships: { - target: { - data: { - id: evt.target.getAttribute('node_id') + '-' + evt.target.getAttribute('collection_id'), - type: 'collection-submission', - } - } - } - } - }; - - var request = $osf.ajaxJSON( - 'POST', - collectionsActionsURL, - { - data: payload, - isCors: true - } - ); - request.done(function(resp) { - location.reload(); - }); - }); - - $('#collections-header').on('click', function (evt) { - if ($('#collections-header>.pull-left').css('display') === 'block') { - $('.collection-pencil').css('display', 'inherit'); - $('#collections-header>.pull-left').css('display', 'none'); - $('#collections-header').css('height', '0px'); - $('#collections-header').css('margin', '0px'); - $('#collections-caret-down').css('padding', '20px'); - $('#collections-caret-down>.fa').toggleClass('fa-angle-down'); - $('#collections-caret-down>.fa').toggleClass(' fa-angle-up'); - } else { - $('.collection-pencil').css('display', 'none'); - $('#collections-header>.pull-left').css('display', 'block'); - $('#collections-header').css('height', 'inherit'); - $('#collections-header').css('margin', '10px'); - $('#collections-caret-down').css('padding', '10px'); - $('#collections-caret-down>.fa').toggleClass('fa-angle-down'); - $('#collections-caret-down>.fa').toggleClass(' fa-angle-up'); - - } - }); - - var AddComponentButton = m.component(AddProject, { - buttonTemplate: m('.btn.btn-sm.btn-default[data-toggle="modal"][data-target="#addSubComponent"]', {onclick: function() { - $osf.trackClick('project-dashboard', 'add-component', 'open-add-project-modal'); - }}, 'Add Component'), - modalID: 'addSubComponent', - title: 'Create new component', - parentID: window.contextVars.node.id, - parentTitle: window.contextVars.node.title, - categoryList: nodeCategories, - stayCallback: function() { - // We need to reload because the components list needs to be re-rendered serverside - window.location.reload(); - }, - trackingCategory: 'project-dashboard', - trackingAction: 'add-component', - contributors: window.contextVars.node.contributors, - currentUserCanEdit: window.contextVars.currentUser.canEdit - }); - - if (!ctx.node.isRetracted) { - if (ctx.node.institutions.length && !ctx.node.anonymous) { - m.mount(document.getElementById('instLogo'), m.component(institutionLogos, {institutions: window.contextVars.node.institutions})); - } - $('#contributorsList').osfToggleHeight(); - - // Recent Activity widget - m.mount(document.getElementById('logFeed'), m.component(LogFeed.LogFeed, {node: node})); - - // Treebeard Files view - var urlFilesGrid = nodeApiUrl + 'files/grid/'; - var promise = m.request({ method: 'GET', config: $osf.setXHRAuthorization, url: urlFilesGrid}); - promise.then(function (data) { - var newComponentElem = document.getElementById('newComponent'); - if (window.contextVars.node.isPublic) { - m.mount( - document.getElementById('shareButtonsPopover'), - m.component( - SocialShare.ShareButtonsPopover, - {title: window.contextVars.node.title, url: window.location.href, type: 'link'} - ) - ); - } - if (newComponentElem) { - m.mount(newComponentElem, AddComponentButton); - } - var fangornOpts = { - divID: 'treeGrid', - filesData: data.data, - allowMove: !node.isRegistration, - uploads : true, - showFilter : true, - placement: 'dashboard', - title : undefined, - filterFullWidth : true, // Make the filter span the entire row for this view - xhrconfig: $osf.setXHRAuthorization, - columnTitles : function () { - return [ - { - title: 'Name', - width : '70%', - sort : true, - sortType : 'text' - }, - { - title: 'Modified', - width : '30%', - sort : true, - sortType : 'text' - } - ]; - }, - resolveRows : function (item) { - var tb = this; - item.css = ''; - if(tb.isMultiselected(item.id)){ - item.css = 'fangorn-selected'; - } - if(item.data.permissions && !item.data.permissions.view){ - item.css += ' tb-private-row'; - } - var defaultColumns = [ - { - data: 'name', - folderIcons: true, - filter: true, - custom: Fangorn.DefaultColumns._fangornTitleColumn}, - { - data: 'modified', - folderIcons: false, - filter: false, - custom: Fangorn.DefaultColumns._fangornModifiedColumn - }]; - if (item.parentID) { - item.data.permissions = item.data.permissions || item.parent().data.permissions; - if (item.data.kind === 'folder') { - item.data.accept = item.data.accept || item.parent().data.accept; - } - } - if(item.data.uploadState && (item.data.uploadState() === 'pending' || item.data.uploadState() === 'uploading')){ - return Fangorn.Utils.uploadRowTemplate.call(tb, item); - } - - var configOption = Fangorn.Utils.resolveconfigOption.call(this, item, 'resolveRows', [item]); - return configOption || defaultColumns; - } - }; - var filebrowser = new Fangorn(fangornOpts); - window.contextVars.node.activeAddons = data.data[0].activeAddons; - return promise; - }, function(xhr, textStatus, error) { - Raven.captureMessage('Error retrieving filebrowser', {extra: {url: urlFilesGrid, textStatus: textStatus, error: error}}); - } - - ); - - } - - // Tooltips - $('[data-toggle="tooltip"]').tooltip({container: 'body'}); - - // Tag input - var nodeType = window.contextVars.node.isRegistration ? 'registrations':'nodes'; - var tagsApiUrl = $osf.apiV2Url(nodeType + '/' + window.contextVars.node.id + '/'); - $('#node-tags').tagsInput({ - width: '100%', - interactive: window.contextVars.currentUser.canEditTags, - maxChars: 128, - defaultText: 'Add a tag to enhance discoverability', - onAddTag: function(tag) { - $('#node-tags_tag').attr('data-default', 'Add a tag'); - window.contextVars.node.tags.push(tag); - var payload = { - data: { - type: nodeType, - id: window.contextVars.node.id, - attributes: { - tags: window.contextVars.node.tags - } - } - }; - - var request = $osf.ajaxJSON( - 'PATCH', - tagsApiUrl, - { - data: payload, - isCors: true - } - ); - - request.fail(function(xhr, textStatus, error) { - window.contextVars.node.tags.splice(window.contextVars.node.tags.indexOf(tag),1); - Raven.captureMessage('Failed to add tag', { - extra: { - tag: tag, url: tagsApiUrl, textStatus: textStatus, error: error - } - }); - }); - }, - onRemoveTag: function(tag) { - if (!tag) { - return false; - } - window.contextVars.node.tags.splice(window.contextVars.node.tags.indexOf(tag),1); - var payload = { - data: { - type: nodeType, - id: window.contextVars.node.id, - attributes: { - tags: window.contextVars.node.tags - } - } - }; - - var request = $osf.ajaxJSON( - 'PATCH', - tagsApiUrl, - { - data: payload, - isCors: true - } - ); - - request.fail(function(xhr, textStatus, error) { - window.contextVars.node.tags.push(tag); - // Suppress "tag not found" errors, as the end result is what the user wanted (tag is gone)- eg could be because two people were working at same time - if (xhr.status !== 409) { - $osf.growl('Error', 'Could not remove tag'); - Raven.captureMessage('Failed to remove tag', { - extra: { - tag: tag, url: tagsApiUrl, textStatus: textStatus, error: error - } - }); - } - }); - } - }); - $('#node-tags_tag').attr('aria-label', 'Tags Input'); - - // allows inital default message to fit on empty tag - if(!$('.tag').length){ - $('#node-tags_tag').css('width', '250px'); - } - - $('#addPointer').on('shown.bs.modal', function(){ - if(!$osf.isIE()){ - $('#addPointer input').focus(); - } - }); - - // Limit the maximum length that you can type when adding a tag - $('#node-tags_tag').attr('maxlength', '128'); - - // Wiki widget markdown rendering - if (ctx.wikiWidget) { - // Render math in the wiki widget - var markdownElement = $('#markdownRender'); - mathrender.mathjaxify(markdownElement); - - // Render the raw markdown of the wiki - var request = $.ajax({ - url: ctx.urls.wikiContent - }); - request.done(function(resp) { - var rawText; - if(resp.wiki_content){ - rawText = resp.wiki_content; - } else if(window.contextVars.currentUser.canEdit) { - rawText = '*Add important information, links, or images here to describe your project.*'; - } else { - rawText = '*No wiki content.*'; - } - - var renderedText = ctx.renderedBeforeUpdate ? oldMd.render(rawText) : md.render(rawText); - // don't truncate the text when length = 400 - var truncatedText = $.truncate(renderedText, {length: 401}); - markdownElement.html(truncatedText); - mathrender.mathjaxify(markdownElement); - markdownElement.show(); - }); - } - - // Remove delete UI if not contributor - if (!window.contextVars.currentUser.canEditTags) { - $('a[title="Removing tag"]').remove(); - $('span.tag span').each(function(idx, elm) { - $(elm).text($(elm).text().replace(/\s*$/, '')); - }); - } - - // Show or hide collection details - if ($('.collection-details').length) { - $('.collection-details').each( function() { - var caret = '#' + $(this).attr('id') + '-toggle'; - $(this).on('hidden.bs.collapse', function(e) { - $(caret).removeClass('fa-angle-up') - .addClass('fa-angle-down'); - }).on('shown.bs.collapse', function(e) { - $(caret).removeClass('fa-angle-down') - .addClass('fa-angle-up'); - }); - }); - } -}); diff --git a/website/static/js/pages/wiki-edit-page.js b/website/static/js/pages/wiki-edit-page.js deleted file mode 100644 index f9f40ff918d..00000000000 --- a/website/static/js/pages/wiki-edit-page.js +++ /dev/null @@ -1,222 +0,0 @@ -'use strict'; - -var $ = require('jquery'); -var Raven = require('raven-js'); -require('bootstrap-editable'); -require('osf-panel'); - -var WikiPage = require('wikiPage'); - -require('ace-noconflict'); -require('ace-mode-markdown'); -require('ace-ext-language_tools'); -require('addons/wiki/static/ace-markdown-snippets.js'); -require('../../vendor/ace-plugins/spellcheck_ace.js'); - -var WikiMenu = require('../wikiMenu'); -var Comment = require('js/comment'); //jshint ignore:line -var $osf = require('js/osfHelpers'); - -var ctx = window.contextVars.wiki; // mako context variables - -var editable = (ctx.panelsUsed.indexOf('edit') !== -1); -var viewable = (ctx.panelsUsed.indexOf('view') !== -1); -var comparable = (ctx.panelsUsed.indexOf('compare') !== -1); -var menuVisible = (ctx.panelsUsed.indexOf('menu') !== -1); - -var viewVersion = ctx.versionSettings.view || (editable ? 'preview' : 'current'); -var compareVersion = ctx.versionSettings.compare || 'previous'; - -var wikiPageOptions = { - editVisible: editable, - viewVisible: viewable, - compareVisible: comparable, - menuVisible: menuVisible, - canEdit: ctx.canEdit, - viewVersion: viewVersion, - compareVersion: compareVersion, - urls: ctx.urls, - metadata: ctx.metadata -}; - -var wikiPage = new WikiPage('#wikiPageContext', wikiPageOptions); - - -// Edit wiki page name -if (ctx.canEditPageName) { - // Initialize editable wiki page name - var $pageName = $('#pageName'); - $.fn.editable.defaults.mode = 'inline'; - $pageName.editable({ - type: 'text', - send: 'always', - url: ctx.urls.rename, - ajaxOptions: { - type: 'put', - contentType: 'application/json', - dataType: 'json' - }, - validate: function(value) { - if($.trim(value) === ''){ - return 'The wiki page name cannot be empty.'; - } else if(value.length > 100){ - return 'The wiki page name cannot be more than 100 characters.'; - } - }, - params: function(params) { - return JSON.stringify(params); - }, - success: function(response, value) { - window.location.href = ctx.urls.base + encodeURIComponent(value) + '/'; - }, - error: function(response) { - var msg = response.responseJSON.message_long; - if (msg) { - return msg; - } else { - // Log unexpected error with Raven - Raven.captureMessage('Error in renaming wiki', { - extra: { - url: ctx.urls.rename, - responseText: response.responseText, - statusText: response.statusText - } - }); - return 'An unexpected error occurred. Please try again.'; - } - } - }); -} - -// Apply panels -$(document).ready(function () { - var errorMsg = $('#wikiErrorMessage'); - var grid = $('#grid'); - // Treebeard Wiki Menu - $.ajax({ - url: ctx.urls.grid - }) - .done(function (data) { - new WikiMenu(data, ctx.wikiID, ctx.canEdit); - }) - .fail(function(xhr, status, error) { - grid.addClass('hidden'); - errorMsg.removeClass('hidden'); - errorMsg.append('

Could not retrieve wiki pages. If this issue persists, ' + - 'please report it to ' + $osf.osfSupportLink()); - Raven.captureMessage('Could not GET wiki menu pages', { - extra: { url: ctx.urls.grid, status: status, error: error } - }); - }); - - var bodyElement = $('body'); - - $('*[data-osf-panel]').osfPanel({ - buttonElement : '.switch', - onSize : 'xs', - 'onclick' : function (event, title, buttonState, thisbtn, col) { - // this = all the column elements; an array - // title = Text of the button - // buttonState = the visibility of column after click, taen from data-osf-toggle attribute, - // thisbtn = $(this); - // col = the $() for the column this button links to - - // Determine if any columns are visible - var visibleColumns = this.filter(function (i, element) { - return $(element).is(':visible'); - }); - - if (visibleColumns.length === 0) { - thisbtn.click(); - return; - } - - bodyElement.trigger('togglePanel', [ - title.toLowerCase(), - buttonState - ]); - if (typeof editor !== 'undefined') { ace.edit(editor).resize(); } // jshint ignore: line - }, - complete : function() { - if (typeof editor !== 'undefined') { ace.edit(editor).resize(); } // jshint ignore: line - } - }); - - var panelToggle = $('.panel-toggle'); - var panelExpand = $('.panel-expand'); - $('.panel-collapse').on('click', function () { - var el = $(this).closest('.panel-toggle'); - el.children('.osf-panel').addClass('hidden'); - el.children('.osf-panel').addClass('visible-xs'); - panelToggle.removeClass('col-sm-3').addClass('col-sm-1'); - panelExpand.removeClass('col-sm-9').addClass('col-sm-11'); - el.children('.panel-collapsed').removeClass('hidden'); - el.children('.panel-collapsed').removeClass('visible-xs'); - $('.wiki-nav').removeClass('hidden'); - - bodyElement.trigger('toggleMenu', [false]); - }); - $('.panel-collapsed .panel-heading').on('click', function () { - var el = $(this).parent(); - var toggle = el.closest('.panel-toggle'); - toggle.children('.osf-panel').removeClass('hidden'); - toggle.children('.osf-panel').removeClass('visible-xs'); - el.addClass('hidden'); - panelToggle.removeClass('col-sm-1').addClass('col-sm-3'); - panelExpand.removeClass('col-sm-11').addClass('col-sm-9'); - $('.wiki-nav').addClass('hidden'); - bodyElement.trigger('toggleMenu', [true]); - }); - - // Tooltip - $('[data-toggle="tooltip"]').tooltip(); -}); - -var $comments = $('.comments'); -if ($comments.length && window.contextVars.wiki.wikiID !== null) { - var options = { - nodeId: window.contextVars.node.id, - nodeApiUrl: window.contextVars.node.urls.api, - isRegistration: window.contextVars.node.isRegistration, - page: 'wiki', - rootId: window.contextVars.wiki.wikiID, - fileId: null, - canComment: window.contextVars.currentUser.canComment, - currentUser: window.contextVars.currentUser, - pageTitle: window.contextVars.wiki.wikiName, - inputSelector: '.atwho-input' - }; - Comment.init('#commentsLink', '.comment-pane', options); -} - -// Disable backspace sending you back a page in firefox. This is just a usability fix because users -// tend to click out of the text box while it loads MFR embeds, then press backspace, believing the -// cursor is still active. -// https://stackoverflow.com/questions/1495219/how-can-i-prevent-the-backspace-key-from-navigating-back -$(document).unbind('keydown').bind('keydown', function (event) { - if (event.keyCode === 8) { - var doPrevent = true; - var types = ['text', 'password', 'file', 'search', 'email', 'number', 'date', 'color', 'datetime', 'datetime-local', 'month', 'range', 'search', 'tel', 'time', 'url', 'week']; - var d = $(event.srcElement || event.target); - var disabled = d.prop('readonly') || d.prop('disabled'); - if (!disabled) { - if (d[0].isContentEditable) { - doPrevent = false; - } else if (d.is('input')) { - var type = d.attr('type'); - if (type) { - type = type.toLowerCase(); - } - if (types.indexOf(type) > -1) { - doPrevent = false; - } - } else if (d.is('textarea')) { - doPrevent = false; - } - } - if (doPrevent) { - event.preventDefault(); - return false; - } - } -}); diff --git a/website/templates/base.mako b/website/templates/base.mako index 51abe36b06a..d1f08a8ff97 100644 --- a/website/templates/base.mako +++ b/website/templates/base.mako @@ -203,7 +203,7 @@

Start managing your projects on the OSF today.

Free and easy to use, the Open Science Framework supports the entire research lifecycle: planning, execution, reporting, archiving, and discovery.

- Create an Account + Create an Account Learn More Hide this message diff --git a/website/templates/collection_submission_cancel.html.mako b/website/templates/collection_submission_cancel.html.mako index 6ee11c1af7c..007d1846da9 100644 --- a/website/templates/collection_submission_cancel.html.mako +++ b/website/templates/collection_submission_cancel.html.mako @@ -10,7 +10,7 @@ % if collection_provider: ${collection_provider_name} % else: - ${collection_provider_name} + ${collection_provider_name} % endif was canceled. If you wish to be associated with the collection, you will need to request to be added again. @@ -20,7 +20,7 @@ % if collection_provider: ${collection_provider_name} % else: - ${collection_provider_name} + ${collection_provider_name} % endif If you wish to be associated with the collection, an admin will need to request addition again. % endif diff --git a/website/templates/collection_submission_removed_private.html.mako b/website/templates/collection_submission_removed_private.html.mako index 726de7f2077..6d97ce0fedb 100644 --- a/website/templates/collection_submission_removed_private.html.mako +++ b/website/templates/collection_submission_removed_private.html.mako @@ -11,7 +11,7 @@ % if collection_provider: ${collection_provider_name} % else: - ${collection_provider_name} + ${collection_provider_name} % endif . If you wish to be associated with the collection, you will need to request addition to the collection again. % else: @@ -20,7 +20,7 @@ % if collection_provider: ${collection_provider_name} % else: - ${collection_provider_name} + ${collection_provider_name} % endif It will need to be re-submitted to be included in the collection again. % endif diff --git a/website/templates/file_operation_failed.html.mako b/website/templates/file_operation_failed.html.mako index eef83a49cbd..fa9d7f8ebb8 100644 --- a/website/templates/file_operation_failed.html.mako +++ b/website/templates/file_operation_failed.html.mako @@ -72,7 +72,6 @@
diff --git a/website/templates/file_operation_success.html.mako b/website/templates/file_operation_success.html.mako index cf692dae0bd..16c63963638 100644 --- a/website/templates/file_operation_success.html.mako +++ b/website/templates/file_operation_success.html.mako @@ -71,7 +71,6 @@ diff --git a/website/templates/notify_base.mako b/website/templates/notify_base.mako index 676868b704b..816ae3fbcf0 100644 --- a/website/templates/notify_base.mako +++ b/website/templates/notify_base.mako @@ -119,9 +119,6 @@ Center For Open Science, All rights reserved. | Privacy Policy

-

- 210 Ridge McIntire Road, Suite 500, Charlottesville, VA 22903-5083 -

${self.footer()}

diff --git a/website/templates/project/edit_draft_registration.mako b/website/templates/project/edit_draft_registration.mako deleted file mode 100644 index 2eed807abcf..00000000000 --- a/website/templates/project/edit_draft_registration.mako +++ /dev/null @@ -1,94 +0,0 @@ -<%inherit file="project/project_base.mako" /> -<%def name="title()">Edit ${node['title']} registration - -
-
-
-

Edit draft registration

-
-
-
-
-
-
-
-
-
- -
-
- % if draft['registration_schema']['schema_name'] != 'Open-Ended Registration': - -
-
- -
-
-
-
-
-
- % endif - -
-
-
-
-
- -
- - Last auto-saved: - - - - - Responses to some questions are invalid or missing where required. - - - -
-
- - - Preview for submission - - - - Next Page - -
-
-
-
-
-
-
-
- -<%def name="javascript_bottom()"> - ${parent.javascript_bottom()} - - - - - -<%include file="project/registration_editor_templates.mako" /> diff --git a/website/templates/project/project.mako b/website/templates/project/project.mako index edd88d87d65..111b6799ed1 100644 --- a/website/templates/project/project.mako +++ b/website/templates/project/project.mako @@ -842,4 +842,4 @@ ${parent.javascript_bottom()} % endfor - + \ No newline at end of file diff --git a/website/templates/public/forgot_password.mako b/website/templates/public/forgot_password.mako index 63d32ffd7f6..73a0f82b09e 100644 --- a/website/templates/public/forgot_password.mako +++ b/website/templates/public/forgot_password.mako @@ -42,7 +42,7 @@
-
Back to OSF
+
Back to OSF
% endif diff --git a/website/templates/public/pages/preprint_landing.mako b/website/templates/public/pages/preprint_landing.mako deleted file mode 100644 index b405eaa38ab..00000000000 --- a/website/templates/public/pages/preprint_landing.mako +++ /dev/null @@ -1,19 +0,0 @@ -<%inherit file="base.mako"/> - -<%def name="title()">Preprints - -<%def name="content()"> -

Preprints service is not activated.

-
    -
  • Set the following in local.py:
  • -
    USE_EXTERNAL_EMBER = True
    -EXTERNAL_EMBER_APPS = {
    -  'preprints': {
    -    'url': '/preprints/',
    -    'server': 'http://localhost:4200',
    -    'path': '/preprints/'
    -  }
    -}
    -
  • Start the preprints container with docker-compose up -d preprints.
  • -
- diff --git a/website/templates/public/pages/registries_landing.mako b/website/templates/public/pages/registries_landing.mako deleted file mode 100644 index ff974f4e270..00000000000 --- a/website/templates/public/pages/registries_landing.mako +++ /dev/null @@ -1,19 +0,0 @@ -<%inherit file="base.mako"/> - -<%def name="title()">Registries - -<%def name="content()"> -

Registries service is not activated.

-
    -
  • Set the following in local.py:
  • -
    USE_EXTERNAL_EMBER = True
    -EXTERNAL_EMBER_APPS = {
    -  'registries': {
    -    'url': '/registries/',
    -    'server': 'http://localhost:4300',
    -    'path': '/registries/'
    -  }
    -}
    -
  • Start the registries container with docker-compose up -d registries.
  • -
- diff --git a/website/templates/public/pages/reviews_landing.mako b/website/templates/public/pages/reviews_landing.mako deleted file mode 100644 index 0a7fa40575e..00000000000 --- a/website/templates/public/pages/reviews_landing.mako +++ /dev/null @@ -1,19 +0,0 @@ -<%inherit file="base.mako"/> - -<%def name="title()">OSF Reviews - -<%def name="content()"> -

Reviews service is not activated.

-
    -
  • Set the following in local.py:
  • -
    USE_EXTERNAL_EMBER = True
    -EXTERNAL_EMBER_APPS = {
    -  'reviews': {
    -    'url': '/reviews/',
    -    'server': 'http://localhost:4400',
    -    'path': '/reviews/'
    -  }
    -}
    -
  • Start the reviews container with docker-compose up -d reviews.
  • -
- diff --git a/website/views.py b/website/views.py index 701f813d59b..1a4bf4942da 100644 --- a/website/views.py +++ b/website/views.py @@ -3,12 +3,10 @@ from rest_framework import status as http_status import logging import math -import os -import requests from urllib.parse import unquote from django.apps import apps -from flask import request, send_from_directory, Response, stream_with_context +from flask import request, Response from framework.auth import Auth from framework.auth.decorators import must_be_logged_in, is_contributor_or_public_resource @@ -21,21 +19,18 @@ from addons.osfstorage.models import Region, OsfStorageFile -from osf import features, exceptions -from osf.models import Guid, Preprint, AbstractNode, Node, DraftNode, Registration, BaseFileNode +from osf import exceptions +from osf.models import Guid, Preprint, AbstractNode, Node, DraftNode, Registration -from website.settings import EXTERNAL_EMBER_APPS, PROXY_EMBER_APPS, EXTERNAL_EMBER_SERVER_TIMEOUT, DOMAIN -from website.ember_osf_web.decorators import ember_flag_is_active -from website.ember_osf_web.views import use_ember_app +from website.settings import DOMAIN from website.project.decorators import check_contributor_auth from website.project.model import has_anonymous_link from osf.utils import permissions from osf.metadata.tools import pls_gather_metadata_file -from api.waffle.utils import storage_i18n_flag_active, flag_is_active +from api.waffle.utils import storage_i18n_flag_active logger = logging.getLogger(__name__) -ember_osf_web_dir = os.path.abspath(os.path.join(os.getcwd(), EXTERNAL_EMBER_APPS['ember_osf_web']['path'])) def serialize_contributors_for_summary(node, max_count=3): @@ -131,19 +126,13 @@ def serialize_node_summary(node, auth, primary=True, show_path=False): return summary -def index(): - return use_ember_app() def find_bookmark_collection(user): Collection = apps.get_model('osf.Collection') return Collection.objects.get(creator=user, deleted__isnull=True, is_bookmark_collection=True) -@must_be_logged_in -def dashboard(auth): - return use_ember_app() @must_be_logged_in -@ember_flag_is_active(features.EMBER_MY_PROJECTS) def my_projects(auth): user = auth.user @@ -175,6 +164,14 @@ def paginate(items, total, page, size): return paginated_items, pages +def index(): + return redirect('/my-projects/') + + +def dashboard(): + return redirect('/my-projects/') + + def reproducibility(): return redirect('/ezcuj/wiki') @@ -230,13 +227,6 @@ def resolve_guid_download(guid, provider=None): return proxy_url(_build_guid_url(unquote(resource.deep_url))) -def stream_emberapp(server, directory): - if PROXY_EMBER_APPS: - resp = requests.get(server, stream=True, timeout=EXTERNAL_EMBER_SERVER_TIMEOUT) - return Response(stream_with_context(resp.iter_content()), resp.status_code) - return send_from_directory(directory, 'index.html') - - def _build_guid_url(base, suffix=None): url = '/'.join([ each.strip('/') for each in [base, suffix] @@ -298,41 +288,9 @@ def resolve_guid(guid, suffix=None): format_arg = request.args.get('format') if format_arg: return guid_metadata_download(guid, resource=resource, metadata_format=format_arg) - else: - return use_ember_app() - - # Stream to ember app if resource has emberized view - if isinstance(resource, Preprint): - if resource.provider.domain_redirect_enabled: - return redirect(resource.absolute_url, http_status.HTTP_301_MOVED_PERMANENTLY) - return use_ember_app() - - elif isinstance(resource, Registration) and (clean_suffix in ('', 'comments', 'links', 'components', 'resources',)) and flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): - return use_ember_app() - - elif isinstance(resource, Registration) and clean_suffix and clean_suffix.startswith('metadata') and flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE): - return use_ember_app() - - elif isinstance(resource, Registration) and (clean_suffix in ('files', 'files/osfstorage')) and flag_is_active(request, features.EMBER_REGISTRATION_FILES): - return use_ember_app() - - elif isinstance(resource, Registration) and clean_suffix and (clean_suffix.startswith('recent-activity')): - return use_ember_app() - - elif isinstance(resource, Node) and clean_suffix and clean_suffix.startswith('files') and flag_is_active(request, features.EMBER_PROJECT_FILES): - return use_ember_app() - - elif isinstance(resource, Node) and clean_suffix and (clean_suffix.startswith('metadata') or clean_suffix.startswith('components') or clean_suffix.startswith('links')): - return use_ember_app() - - elif isinstance(resource, OsfStorageFile) and isinstance(resource.target, DraftNode): - return use_ember_app() - elif isinstance(resource, BaseFileNode) and resource.is_file and not isinstance(resource.target, Preprint): - if isinstance(resource.target, Registration) and flag_is_active(request, features.EMBER_FILE_REGISTRATION_DETAIL): - return use_ember_app() - if isinstance(resource.target, Node) and flag_is_active(request, features.EMBER_FILE_PROJECT_DETAIL): - return use_ember_app() + if isinstance(resource, Preprint) and resource.provider.domain_redirect_enabled: + return redirect(resource.absolute_url, http_status.HTTP_301_MOVED_PERMANENTLY) # Redirect to legacy endpoint for Nodes, Wikis etc. url = _build_guid_url(unquote(resource.deep_url), suffix) diff --git a/yarn.lock b/yarn.lock index 70f26dd5a2f..c3d2fececda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,97 +7,56 @@ resolved "https://registry.yarnpkg.com/@centerforopenscience/list-of-licenses/-/list-of-licenses-1.1.0.tgz#2a4379633409205047e723e21cd818560a29ab45" integrity sha512-EGU7gpRXczqC4TAlfKBiLzRaopxxZkL86kwS8/qdZdmRjTpG872z+bRd5E4ZJivxHBLpVpts5nK/bz4MsbdhTA== -"@centerforopenscience/markdown-it-atrules@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@centerforopenscience/markdown-it-atrules/-/markdown-it-atrules-0.1.1.tgz#16616c0ac54bb29700f99a8aab76dd805b48ce59" - integrity sha512-r3ZTJESVCpdU9tOQe2PVcUkJmrPA/1itvCtHpsJrhXMj/nY7JcESjgMSFEe432DcofXDzRF8kXW1XWQuH1BfMw== - dependencies: - np "^3.0.4" - -"@centerforopenscience/markdown-it-imsize@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@centerforopenscience/markdown-it-imsize/-/markdown-it-imsize-2.0.1.tgz#bdfc7602bfffe9faeed9ee0278185535d8b001ae" - integrity sha512-PV6UGXJobGfJjt+H/A4wIOyrobjflVIrTYvE1RAQU/TTmCEVvnT5Os4TfziEWhKNfaB/IGRTphjQI8jDokPdjw== - -"@centerforopenscience/markdown-it-toc@~1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@centerforopenscience/markdown-it-toc/-/markdown-it-toc-1.1.1.tgz#633c6367cf783a51a080e75a9cd62fd62037e140" - integrity sha512-xzfwi99vziqpE8cEmcAWiSNGA2pCg/F5XO/GsWo89J1qzFt4udlOiqzW8+yjtfEPQhDY3KLB62QVN4yudeBUYA== - -"@centerforopenscience/markdown-it-video@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@centerforopenscience/markdown-it-video/-/markdown-it-video-1.0.0.tgz#4c1ab932ccb25c17a8992daa12168d0aea622664" - integrity sha512-6TOHqcRy7eg09aCcXLYCvLk87eMuFB8P1rBonpjJPcz++FQdEL5834c1Vq8vCePabKY2Scg3DNagRIblagXjXg== - "@centerforopenscience/osf-style@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@centerforopenscience/osf-style/-/osf-style-1.9.0.tgz#0ab5cb17e2c531aafcc19e226f36ff86b734116e" integrity sha512-R9IBVbz4eb/NkoM5TZGH46T9m5jspwK0H605O0oSMggHZPcTrf5gAHw0axeC26nKmEpz2FSXjvm84ziPNvhsvA== -"@fortawesome/fontawesome-common-types@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.0.1.tgz#e9ab94b1ca93e7020e3c7eda2ef1ba8cca8ba1dc" - integrity sha512-0VpNtO5cNe1/HQWMkl4OdncYK/mv9hnBte0Ew0n6DMzmo3Q3WzDFABHm6LeNTipt5zAyhQ6Ugjiu8aLaEjh1gg== +"@fortawesome/fontawesome-common-types@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.2.0.tgz#ae54831ab5974bc1a64e8b07410f2da2b4abf87f" + integrity sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw== "@fortawesome/fontawesome-free@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-7.0.1.tgz#c1ac7f07ba2df47d1de7b7236fad25c4e6ca5076" - integrity sha512-RLmb9U6H2rJDnGxEqXxzy7ANPrQz7WK2/eTjdZqyU9uRU5W+FkAec9uU5gTYzFBH7aoXIw2WTJSCJR4KPlReQw== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-7.2.0.tgz#188c1053ce422ad1f934d7df242a973fcb89636d" + integrity sha512-3DguDv/oUE+7vjMeTSOjCSG+KeawgVQOHrKRnvUuqYh1mfArrh7s+s8hXW3e4RerBA1+Wh+hBqf8sJNpqNrBWg== "@fortawesome/fontawesome-svg-core@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.0.1.tgz#f5f7bbfe09e7cc35fd30eefe6be018d2e9c5dd4d" - integrity sha512-x0cR55ILVqFpUioSMf6ebpRCMXMcheGN743P05W2RB5uCNpJUqWIqW66Lap8PfL/lngvjTbZj0BNSUweIr/fHQ== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.2.0.tgz#813550a5e8946a798e170d3f7331a685f8f8a550" + integrity sha512-6639htZMjEkwskf3J+e6/iar+4cTNM9qhoWuRfj9F3eJD6r7iCzV1SWnQr2Mdv0QT0suuqU8BoJCZUyCtP9R4Q== dependencies: - "@fortawesome/fontawesome-common-types" "7.0.1" + "@fortawesome/fontawesome-common-types" "7.2.0" "@fortawesome/free-brands-svg-icons@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-7.0.1.tgz#2a975ae2a26710cb2b34c25d4fe706dcd4747f69" - integrity sha512-6xPmn5SrND/GM0+W33E77x05+aDn6RpR02eWd8eLdN0IxY0vXa5yU/ugaAKloOVxiG9w2330TSRsbJYL6c57Ow== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-7.2.0.tgz#36f4306e671ad0acd23c1db96bde72e47d93e596" + integrity sha512-VNG8xqOip1JuJcC3zsVsKRQ60oXG9+oYNDCosjoU/H9pgYmLTEwWw8pE0jhPz/JWdHeUuK6+NQ3qsM4gIbdbYQ== dependencies: - "@fortawesome/fontawesome-common-types" "7.0.1" + "@fortawesome/fontawesome-common-types" "7.2.0" "@fortawesome/react-fontawesome@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-3.0.2.tgz#275ab6bc04977e145b072ba18c24779eb3427073" - integrity sha512-cmp/nT0pPC7HUALF8uc3+D5ECwEBWxYQbOIHwtGUWEu72sWtZc26k5onr920HWOViF0nYaC+Qzz6Ln56SQcaVg== - -"@samverschueren/stream-to-observable@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" - integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ== - dependencies: - any-observable "^0.3.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" + version "3.3.0" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-3.3.0.tgz#020364bdd71d785ffbb0e61425f53325f78fc647" + integrity sha512-EHmHeTf8WgO29sdY3iX/7ekE3gNUdlc2RW6mm/FzELlHFKfTrA9S4MlyquRR+RRCRCn8+jXfLFpLGB2l7wCWyw== URIjs@^1.14.1: version "1.16.1" resolved "https://registry.yarnpkg.com/URIjs/-/URIjs-1.16.1.tgz#edebc678b8b74b26b05d2b481e12383f5ae04b8b" - integrity sha1-7evGeLi3SyawXStIHhI4P1rgS4s= + integrity sha512-ycFsR7J7p7Q+iJA4oVQP9tEnBEA7N/JD5RiOkLAhEeAmR1djRvZBpKCsWhmDaEoBNJLMhaCVpfLcRgqfaG6COw== acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= + integrity sha512-GKp5tQ8h0KMPWIYGRHHXI1s5tUpZixZ3IHF2jAu42wSCf6In/G873s6/y4DdKdhWvzhu1T6mE1JgvnhAKqyYYQ== dependencies: acorn "^4.0.3" acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + integrity sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug== acorn@^5.0.0: version "5.7.4" @@ -117,7 +76,7 @@ ajv-keywords@^3.1.0: ajv@^5.0.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= + integrity sha512-Ajr4IcMXq/2QmMkEmSvxqfLN5zGmJ92gHXAeOXq1OekoH2rfDNsgdDoL2f7QaRCy7G/E6TpxBVdRuNraMztGHw== dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -125,9 +84,9 @@ ajv@^5.0.0: json-schema-traverse "^0.3.0" ajv@^6.1.0: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + version "6.14.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" + integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -137,39 +96,27 @@ ajv@^6.1.0: alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + integrity sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ== amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= - dependencies: - string-width "^2.0.0" - -ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== ansi-styles@^3.2.1: version "3.2.1" @@ -178,11 +125,6 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -any-observable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" - integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== - aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -195,71 +137,43 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + version "1.5.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.1.tgz#038ab248e4ff078e7bc2485ba6e6388466c78f76" + integrity sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A== dependencies: - object-assign "^4.1.1" - util "0.10.3" + object.assign "^4.1.4" + util "^0.10.4" assets-webpack-plugin@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/assets-webpack-plugin/-/assets-webpack-plugin-2.3.0.tgz#3e5fb861a19f1a9748aa02f56b8a03d7476ad0db" - integrity sha1-Pl+4YaGfGpdIqgL1a4oD10dq0Ns= + integrity sha512-PqKXArZTW7wTnRp7sttlYbhBgNsa07z6Epk6csXa5ArkbGhlOexsJ4xAJqtdXslsgcP+xy3/qx3xG0W9+FAG4g== dependencies: camelcase "^1.2.1" escape-string-regexp "^1.0.3" mkdirp "^0.5.1" async@^2.1.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" autoprefixer@^6.3.1: version "6.7.7" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" - integrity sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ= + integrity sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ== dependencies: browserslist "^1.7.6" caniuse-db "^1.0.30000634" @@ -268,145 +182,26 @@ autoprefixer@^6.3.1: postcss "^5.2.16" postcss-value-parser "^3.2.3" +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== dependencies: chalk "^1.1.3" esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^6.0.0, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-loader@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca" - integrity sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo= - dependencies: - find-cache-dir "^0.1.1" - loader-utils "^0.2.16" - mkdirp "^0.5.1" - object-assign "^4.0.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= + integrity sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg== balanced-match@^1.0.0: version "1.0.2" @@ -434,72 +229,39 @@ bluebird@^3.5.1: integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -body-parser@~1.19.1: - version "1.19.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" - integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.7" - raw-body "2.4.3" - type-is "~1.6.18" + version "4.12.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.3.tgz#2cc2c679188eb35b006f2d0d4710bed8437a769e" + integrity sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g== + +bn.js@^5.2.1, bn.js@^5.2.2: + version "5.2.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.3.tgz#16a9e409616b23fef3ccbedb8d42f13bff80295e" + integrity sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w== bootbox@^5.5.2: - version "5.5.2" - resolved "https://registry.yarnpkg.com/bootbox/-/bootbox-5.5.2.tgz#a4200aa03f12ffe4d07905834e9dfb76e52cee00" - integrity sha512-q8d9VO2A4+q6S0XvovLtqtBUp7uRy0wtDOuuycnoheK2TiAm3um0jOlAOu9ORn9XoT92tdil+p15Dle1mRgSPQ== - dependencies: - bootstrap "^4.4.0" - jquery "^3.5.1" - popper.js "^1.16.0" + version "5.5.3" + resolved "https://registry.yarnpkg.com/bootbox/-/bootbox-5.5.3.tgz#6b32da9c401a22b089e1544797cc9a91f1c35b23" + integrity sha512-B4mnm1DYgNHzoNtD7I0L/fixqvya4EEQy5bFF/yNmGI2Eq3WwVVwdfWf3hoF8KS+EaV4f0uIMqtxB1EAZwZPhQ== bootstrap@3.3.7, bootstrap@~3.3.2: version "3.3.7" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.3.7.tgz#5a389394549f23330875a3b150656574f8a9eb71" - integrity sha1-WjiTlFSfIzMIdaOxUGVldPip63E= + integrity sha512-qcFaisBrcBhTFkz1IUnGDYnX6ZWfFzH8zOixUDtHW9Ip+r+7MfMFav2rzy7cIHc7rgIg7xjhWBoo1mS/U26j4g== -bootstrap@^3.3.7, bootstrap@^4.4.0: +bootstrap@^3.3.7: version "3.4.1" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.4.1.tgz#c3a347d419e289ad11f4033e3c4132b87c081d72" integrity sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA== bower@^1.8.8: - version "1.8.13" - resolved "https://registry.yarnpkg.com/bower/-/bower-1.8.13.tgz#5892f391f47134db88ea93d4c91a31f09792dc58" - integrity sha512-8eWko16JlCTdaZZG70kddHPed17pHEbH8/IjfP4IFkQsfEqRsyNM09Dc8cDBFkSvtQ/2lTea7A+bMhRggG2a+Q== - -boxen@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" + version "1.8.14" + resolved "https://registry.yarnpkg.com/bower/-/bower-1.8.14.tgz#985722a3c1fcd35c93d4136ecbeafbeaaea74e86" + integrity sha512-8Rq058FD91q9Nwthyhw0la9fzpBz0iwZTrt51LWl+w+PnJgZk9J+5wp3nibsJcIUPglMYXr4NRBaR+TUj0OkBQ== brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -507,9 +269,9 @@ brace-expansion@^1.1.7: brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -521,7 +283,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-cipher@^1.0.0: +browserify-cipher@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== @@ -540,28 +302,29 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== +browserify-rsa@^4.0.0, browserify-rsa@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.1.tgz#06e530907fe2949dc21fc3c2e2302e10b1437238" + integrity sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ== dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" + bn.js "^5.2.1" + randombytes "^2.1.0" + safe-buffer "^5.2.1" -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== +browserify-sign@^4.2.3: + version "4.2.5" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.5.tgz#3979269fa8af55ba18aac35deef11b45515cd27d" + integrity sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.2" + browserify-rsa "^4.1.1" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.6.1" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.9" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" @@ -573,7 +336,7 @@ browserify-zlib@^0.2.0: browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: version "1.7.7" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - integrity sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk= + integrity sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw== dependencies: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" @@ -586,7 +349,7 @@ buffer-from@^1.0.0: buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== buffer@^4.3.0: version "4.9.2" @@ -600,24 +363,7 @@ buffer@^4.3.0: builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -c3@^0.4.18: - version "0.4.24" - resolved "https://registry.yarnpkg.com/c3/-/c3-0.4.24.tgz#57b62357098842d38e265a265f6de1e8c6faadd2" - integrity sha512-mVCFtN5ZWUT5UE7ilFQ7KBQ7TUCdKIq6KsDt1hH/1m6gC1tBjvzFTO7fqhaiWHfhNOjjM7makschdhg6DkWQMA== - dependencies: - d3 "~3.5.0" + integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== cacache@^10.0.4: version "10.0.4" @@ -638,42 +384,46 @@ cacache@^10.0.4: unique-filename "^1.1.0" y18n "^4.0.0" -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" + es-errors "^1.3.0" + function-bind "^1.1.2" -camelcase-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= +call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== dependencies: - camelcase "^4.1.0" - map-obj "^2.0.0" - quick-lru "^1.0.0" + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" camelcase@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= + integrity sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g== -camelcase@^4.0.0, camelcase@^4.1.0: +camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw== caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" - integrity sha1-tTTnxzTE+B7F++isoq0kNUuWLGw= + integrity sha512-SBTl70K0PkDUIebbkXrxWqZlHNs0wRgRD6QZ8guctShjbh63gEPfF+Wj0Yw+75f5Y8tSzqAI/NcisYv/cCah2Q== dependencies: browserslist "^1.3.6" caniuse-db "^1.0.30000529" @@ -681,19 +431,14 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30001312" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001312.tgz#efb31cb54e5f4714126d8c35292666c9b7290c87" - integrity sha512-4eJfCSGxsF9JcQXBLdHclxkpLWv+Va7Y6QESYCWSdrR8b8x16TxUjCoOK/kU7SFC0BdcuK0nvt6ZkM59Q03LjQ== - -capture-stack-trace@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" - integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== + version "1.0.30001781" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001781.tgz#7bc16b681ec25e23bd8b2e02067b9cede707c778" + integrity sha512-gNw4Hl6IfkgyGMNzgGRWrnalOUASAYFiCFywQemHI9OU16PC6TRRhHEnR7taYC2/Mad/nDLkzXAEtejGuNsUfg== -chalk@^1.0.0, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -701,7 +446,7 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1: +chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -710,28 +455,19 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= - chownr@^1.0.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -ci-info@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== - cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + version "1.0.7" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.7.tgz#bd094bfef42634ccfd9e13b9fc73274997111e39" + integrity sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.2" clap@^1.0.9: version "1.2.3" @@ -740,68 +476,36 @@ clap@^1.0.9: dependencies: chalk "^1.1.3" -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= - -cli-cursor@^2.0.0, cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - -cli-truncate@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" - integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= - dependencies: - slice-ansi "0.0.4" - string-width "^1.0.1" - -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== coa@~1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - integrity sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0= + integrity sha512-KAGck/eNAmCL0dcT3BiuYwLbExK6lduR8DxM3C1TyDzaXhZHyZ8ooX5I5+na2e3dPFuibfxrGdorr0/Lr7RYCQ== dependencies: q "^1.1.2" code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== color-convert@^1.3.0, color-convert@^1.9.0: version "1.9.3" @@ -813,7 +517,7 @@ color-convert@^1.3.0, color-convert@^1.9.0: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@^1.0.0: version "1.1.4" @@ -823,14 +527,14 @@ color-name@^1.0.0: color-string@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= + integrity sha512-sz29j1bmSDfoAxKIEU6zwoIZXN6BrFbAMIhfYCNyiZXBDuU/aiHlN84lp/xDzL2ubyFhLDobHIlU1X70XRrMDA== dependencies: color-name "^1.0.0" color@^0.11.0: version "0.11.4" resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= + integrity sha512-Ajpjd8asqZ6EdxQeqGzU5WBhhTfJ/0cA4Wlbre7e5vXfmDSmda7Ov6jeKoru+b0vHcb1CqvuroTHp5zIWzhVMA== dependencies: clone "^1.0.2" color-convert "^1.3.0" @@ -839,7 +543,7 @@ color@^0.11.0: colormin@^1.0.5: version "1.1.2" resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" - integrity sha1-6i90IKcrlogaOKrlnsEkpvcpgTM= + integrity sha512-XSEQUUQUR/lXqGyddiNH3XYFUPYlYr1vXy9rTFMsSOw+J7Q6EQkdlQIrTlYn4TccpsOaUE1PYQNjBn20gwCdgQ== dependencies: color "^0.11.0" css-color-names "0.0.4" @@ -848,7 +552,7 @@ colormin@^1.0.5: colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= + integrity sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w== commander@~2.13.0: version "2.13.0" @@ -858,12 +562,12 @@ commander@~2.13.0: commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.5.0: version "1.6.2" @@ -875,18 +579,6 @@ concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" -configstore@^3.0.0: - version "3.1.5" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.5.tgz#e9af331fadc14dabd544d3e7e76dc446a09a530f" - integrity sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA== - dependencies: - dot-prop "^4.2.1" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -895,26 +587,14 @@ console-browserify@^1.1.0: constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.5.1: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -copy-anything@^2.0.1: - version "2.0.6" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480" - integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw== +copy-anything@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0" + integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== dependencies: - is-what "^3.14.1" + is-what "^4.1.8" copy-concurrently@^1.0.0: version "1.0.5" @@ -928,17 +608,12 @@ copy-concurrently@^1.0.0: rimraf "^2.5.4" run-queue "^1.0.0" -core-js@^2.4.0, core-js@^2.5.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -create-ecdh@^4.0.0: +create-ecdh@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== @@ -946,14 +621,7 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.5.3" -create-error-class@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= - dependencies: - capture-stack-trace "^1.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: +create-hash@^1.1.0, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -964,7 +632,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -979,51 +647,36 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + version "3.12.1" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.1.tgz#bb8921bec9acc81633379aa8f52d69b0b69e0dac" + integrity sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ== dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= + browserify-cipher "^1.0.1" + browserify-sign "^4.2.3" + create-ecdh "^4.0.4" + create-hash "^1.2.0" + create-hmac "^1.1.7" + diffie-hellman "^5.0.3" + hash-base "~3.0.4" + inherits "^2.0.4" + pbkdf2 "^3.1.2" + public-encrypt "^4.0.3" + randombytes "^2.1.0" + randomfill "^1.0.4" css-color-names@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + integrity sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q== -css-loader@^0.28.11, css-loader@~0.26.1: +css-loader@^0.28.11: version "0.28.11" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.11.tgz#c3f9864a700be2711bb5a2462b2389b1a392dab7" integrity sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg== @@ -1059,7 +712,7 @@ cssesc@^3.0.0: cssnano@^3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" - integrity sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg= + integrity sha512-0o0IMQE0Ezo4b41Yrm8U6Rp9/Ag81vNXY1gZMnT1XhO4DpjEf2utKERqWJbOoz3g1Wdc1d3QSta/cIuJ1wSTEg== dependencies: autoprefixer "^6.3.1" decamelize "^1.1.2" @@ -1097,128 +750,66 @@ cssnano@^3.10.0: csso@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - integrity sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U= + integrity sha512-FmCI/hmqDeHHLaIQckMhMZneS84yzUZdrWDAvJVVxOwcKE1P1LF9FGmzr1ktIQSxOw6fl3PaQsmfg+GN+VvR3w== dependencies: clap "^1.0.9" source-map "^0.5.3" -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -d3@^3.5.17, d3@~3.5.0: - version "3.5.17" - resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8" - integrity sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -date-fns@^1.27.2: - version "1.30.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" - integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== - -debug@2.6.9, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.6: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" + version "1.0.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.2.tgz#673b5f233bf34d8e602b949429f8171d9121bea3" + integrity sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA== -decamelize-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" + es5-ext "^0.10.64" + type "^2.7.2" -decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: - mimic-response "^1.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= - -del@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" - integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU= +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: - globby "^6.1.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - p-map "^1.1.1" - pify "^3.0.0" - rimraf "^2.2.8" + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +defined@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= - dependencies: - repeating "^2.0.0" - diff@~5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -diffie-hellman@^5.0.0: +diffie-hellman@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== @@ -1232,21 +823,18 @@ domain-browser@^1.1.1: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -dot-prop@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" - integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== - dependencies: - is-obj "^1.0.0" - "dropzone@https://github.com/CenterForOpenScience/dropzone.git#aba21eb6b82cc823ac7a7a53d6e035791c082bae": version "4.3.0" resolved "https://github.com/CenterForOpenScience/dropzone.git#aba21eb6b82cc823ac7a7a53d6e035791c082bae" -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -1258,25 +846,15 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - electron-to-chromium@^1.2.7: - version "1.4.71" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" - integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== + version "1.5.321" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.321.tgz#57a80554e2e7fd65e3689d320f52a64723472d5d" + integrity sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ== -elegant-spinner@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" - integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= - -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== +elliptic@^6.5.3, elliptic@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -1289,7 +867,7 @@ elliptic@^6.5.3: emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + integrity sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng== emojis-list@^3.0.0: version "3.0.0" @@ -1297,27 +875,22 @@ emojis-list@^3.0.0: integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== dependencies: once "^1.4.0" enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= + integrity sha512-ZaAux1rigq1e2nQrztHn4h2ugvpzZxs64qneNah+8Mh/K0CRqJFJc+UoXnUsq+1yX+DmQFPPdVqboKAJ89e0Iw== dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" object-assign "^4.0.1" tapable "^0.2.7" -entities@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" - integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== - errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" @@ -1325,26 +898,44 @@ errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: dependencies: prr "~1.0.1" -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== +error-ex@^1.2.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== dependencies: is-arrayish "^0.2.1" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" + es-errors "^1.3.0" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== dependencies: d "1" es5-ext "^0.10.35" @@ -1353,7 +944,7 @@ es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: es6-map@^0.1.3: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= + integrity sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A== dependencies: d "1" es5-ext "~0.10.14" @@ -1363,31 +954,24 @@ es6-map@^0.1.3: event-emitter "~0.3.5" es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= + version "0.1.6" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.6.tgz#5669e3b2aa01d61a50ba79964f733673574983b8" + integrity sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw== dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" + d "^1.0.1" + es5-ext "^0.10.62" + es6-iterator "~2.0.3" + es6-symbol "^3.1.3" + event-emitter "^0.3.5" + type "^2.7.2" -es6-symbol@^3.1.1, es6-symbol@~3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== +es6-symbol@^3.1.1, es6-symbol@^3.1.3, es6-symbol@~3.1.1: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== dependencies: - d "^1.0.1" - ext "^1.1.2" + d "^1.0.2" + ext "^1.7.0" es6-weak-map@^2.0.1: version "2.0.3" @@ -1402,22 +986,32 @@ es6-weak-map@^2.0.1: escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= + integrity sha512-75IUQsusDdalQEW/G/2esa87J7raqdJF+Ca0/Xm5C3Q58Nr4yVYjZGp/P1+2xiEVgXRrA39dpRb8LcshajbqDQ== dependencies: es6-map "^0.1.3" es6-weak-map "^2.0.1" esrecurse "^4.1.0" estraverse "^4.1.1" +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + esprima@^2.6.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== esrecurse@^4.1.0: version "4.3.0" @@ -1441,10 +1035,10 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -event-emitter@~0.3.5: +event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== dependencies: d "1" es5-ext "~0.10.14" @@ -1462,23 +1056,10 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + integrity sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw== dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -1491,31 +1072,22 @@ execa@^0.7.0: exports-loader@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/exports-loader/-/exports-loader-0.6.3.tgz#57dc78917f709b96f247fa91e69b554c855013c8" - integrity sha1-V9x4kX9wm5byR/qR5ptVTIVQE8g= + integrity sha512-vBQgTnvmEB7qWmr7gzAzJRWptzYhkhvdXeH8sRnS//mIai6MgLZe1crlQ+VWTjCCXLlnhGuiuVMq0YfjA5AUOw== dependencies: loader-utils "0.2.x" source-map "0.1.x" -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== - dependencies: - type "^2.5.0" - -external-editor@^2.0.4, external-editor@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" + type "^2.7.2" fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + integrity sha512-fueX787WZKCV0Is4/T2cyAdM4+x1S3MXXOAhavE1ys/W42SHAPacLTQhucja22QBYrfGw50M2sRiXPtTGv9Ymw== fast-deep-equal@^3.1.1: version "3.1.3" @@ -1532,21 +1104,6 @@ fastparse@^1.1.2: resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== -figures@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - file-loader@^0.11.2: version "0.11.2" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.11.2.tgz#4ff1df28af38719a6098093b88c82c71d1794a34" @@ -1554,36 +1111,19 @@ file-loader@^0.11.2: dependencies: loader-utils "^1.0.2" -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - integrity sha1-yN765XyKUqinhPnjHFfHQumToLk= - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - find-cache-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8= + integrity sha512-46TFiBOzX7xq/PcSWfFwkyjpemdRnMe31UQF+os0y+1W3k95f6R4SEt02Hj4p3X0Mir9gfrkmOtshFidS0VPUg== dependencies: commondir "^1.0.1" make-dir "^1.0.0" pkg-dir "^2.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" @@ -1600,19 +1140,17 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -font-awesome-webpack@0.0.5-beta.2: - version "0.0.5-beta.2" - resolved "https://registry.yarnpkg.com/font-awesome-webpack/-/font-awesome-webpack-0.0.5-beta.2.tgz#9ea5f22f0615d08e76d8db341563649a726286d6" - integrity sha1-nqXyLwYV0I522Ns0FWNkmnJihtY= +for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== dependencies: - css-loader "~0.26.1" - less-loader "~2.2.3" - style-loader "~0.13.1" + is-callable "^1.2.7" from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== dependencies: inherits "^2.0.1" readable-stream "^2.0.0" @@ -1620,7 +1158,7 @@ from2@^2.1.0: fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + integrity sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA== dependencies: graceful-fs "^4.1.2" iferr "^0.1.5" @@ -1630,120 +1168,73 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -github-url-from-git@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/github-url-from-git/-/github-url-from-git-1.5.0.tgz#f985fedcc0a9aa579dc88d7aff068d55cc6251a0" - integrity sha1-+YX+3MCpqledyI16/waNVcxiUaA= + integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.0.3, glob@^7.1.2, glob@^7.1.3: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^7.1.2, glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= - dependencies: - ini "^1.3.4" - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= - dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== gsap@3.9.1: version "3.9.1" @@ -1753,45 +1244,66 @@ gsap@3.9.1: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + integrity sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== -has-yarn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-1.0.0.tgz#89e25db604b725c8f5976fff0addc921b828a5a7" - integrity sha1-ieJdtgS3Jcj1l2//Ct3JIbgopac= +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" -has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +has@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== + +hash-base@^3.0.0, hash-base@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.2.tgz#79d72def7611c3f6e3c3b5730652638001b10a74" + integrity sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg== dependencies: - function-bind "^1.1.1" + inherits "^2.0.4" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + to-buffer "^1.2.1" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== +hash-base@~3.0.4: + version "3.0.5" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" + integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== dependencies: inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + safe-buffer "^5.2.1" hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" @@ -1801,6 +1313,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + highlight.js@~9.18.2: version "9.18.5" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" @@ -1809,20 +1328,12 @@ highlight.js@~9.18.2: hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -1833,43 +1344,27 @@ html-comment-regex@^1.1.0: resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: - safer-buffer ">= 2.1.2 < 3" + safer-buffer ">= 2.1.2 < 3.0.0" icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= + integrity sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg== icss-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" - integrity sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI= + integrity sha512-bsVoyn/1V4R1kYYjLcWLedozAM4FClZUdjE9nIr8uWY7xs78y9DATgwz2wGU7M+7z55KenmmTkN2DVJ7bqzjAA== dependencies: postcss "^6.0.1" @@ -1881,22 +1376,17 @@ ieee754@^1.1.4: iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + integrity sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA== image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" - integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ== imports-loader@^0.6.3: version "0.6.5" resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.6.5.tgz#ae74653031d59e37b3c2fb2544ac61aeae3530a6" - integrity sha1-rnRlMDHVnjezwvslRKxhrq41MKY= + integrity sha512-fYIzBL9JOzJszvfeSGSKVjAtkWEtPUwP+OWiUxIWApcxsYh3iqZWZAp8xjTuhsvqglhqaetxeLLTaYyxIv1d4Q== dependencies: loader-utils "0.2.x" source-map "0.1.x" @@ -1904,276 +1394,130 @@ imports-loader@^0.6.3: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + integrity sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inquirer@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - -inquirer@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" - integrity sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.1.0" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^5.5.2" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -ip-regex@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" - integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + integrity sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg== is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-ci@^1.0.10: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== - dependencies: - ci-info "^1.5.0" +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== +is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - has "^1.0.3" - -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + hasown "^2.0.2" is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== -is-installed-globally@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= - dependencies: - global-dirs "^0.1.0" - is-path-inside "^1.0.0" - -is-npm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-observable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" - integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== - dependencies: - symbol-observable "^1.1.0" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= - dependencies: - path-is-inside "^1.0.1" - -is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: +is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-promise@^2.1.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-scoped@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-scoped/-/is-scoped-1.0.0.tgz#449ca98299e713038256289ecb2b540dc437cb30" - integrity sha1-RJypgpnnEwOCViieyytUDcQ3yzA= - dependencies: - scoped-regex "^1.0.0" - -is-scoped@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-scoped/-/is-scoped-2.1.0.tgz#fef0713772658bdf5bee418608267ddae6d3566d" - integrity sha512-Cv4OpPTHAK9kHYzkzCrof3VJh7H/PrG2MBUMvvJebaaUMbqhm0YAtXnvh0I3Hnj2tMZWwrRROWLSgfJrKqWmlQ== - dependencies: - scoped-regex "^2.0.0" - -is-stream@^1.0.0, is-stream@^1.1.0: +is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== is-svg@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" - integrity sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk= + integrity sha512-Ya1giYJUkcL/94quj0+XGcmts6cETPBW1MiFz1ReJrnDJ680F52qpAEGAEGU0nq96FRGIGPx6Yo1CyPXcOoyGw== dependencies: html-comment-regex "^1.1.0" -is-url-superb@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-url-superb/-/is-url-superb-3.0.0.tgz#b9a1da878a1ac73659047d1e6f4ef22c209d3e25" - integrity sha512-3faQP+wHCGDQT1qReM5zCPx2mxoal6DzbzquFlCYJLWyy4WPTved33ea2xFbX37z4NoriEwZGIYhFtx8RUB5wQ== +is-typed-array@^1.1.14: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: - url-regex "^5.0.0" + which-typed-array "^1.1.16" -is-what@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" - integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== +is-what@^4.1.8: + version "4.1.16" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f" + integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -issue-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/issue-regex/-/issue-regex-2.0.0.tgz#bb1802490394f8083c7a6787247cbf975638ef5d" - integrity sha512-flaQ/45dMqCYSMzBQI/h3bcto6T70uN7kjNnI8n3gQU6no5p+QcnMWBNXkraED0YvbUymxKaqdvgPa09RZQM5A== + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== jquery-ui@>=1.10.4: - version "1.13.1" - resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.13.1.tgz#d0b7a42e73a04c31bb5706adf86f6f8942f64eaa" - integrity sha512-2VlU59N5P4HaumDK1Z3XEVjSvegFbEOQRgpHUBaB2Ak98Axl3hFhJ6RFcNQNuk9SfL6WxIbuLst8dW/U56NSiA== + version "1.14.2" + resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.14.2.tgz#515288b5c730b720acca6e53a0366827ad834053" + integrity sha512-1gSl7PUjyipa2adSr780Ujk16faicrV7PjPPzPtvWk7tTqBnsqp67NNV9jZK2+BIxUPXWSnIUU/LBCgwgGZE+Q== dependencies: - jquery ">=1.8.0 <4.0.0" + jquery ">=1.12.0 <5.0.0" -jquery@>=1.11.0, jquery@>=1.7, "jquery@>=1.8.0 <4.0.0", jquery@^3.5.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" - integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== +jquery@>=1.11.0, "jquery@>=1.12.0 <5.0.0", jquery@>=1.7: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-4.0.0.tgz#95c33ac29005ff72ec444c5ba1cf457e61404fbb" + integrity sha512-TXCHVR3Lb6TZdtw1l3RTLf8RBWVGexdxL6AC8/e0xZKEpBflBsjh9/8LXw+dkNFuOyW9B7iB3O1sP7hS0Kiacg== js-base64@^2.1.9: version "2.6.4" @@ -2190,48 +1534,28 @@ js-md5@^0.7.3: resolved "https://registry.yarnpkg.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2" integrity sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ== -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - integrity sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A= + integrity sha512-eIlkGty7HGmntbV6P/ZlAsoncFLGsNoM27lkTzS+oneY/EiNhj+geqD9ezg/ip+SW6Var0BJU2JtV0vEUZpWVQ== dependencies: argparse "^1.0.7" esprima "^2.6.0" -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - json-loader@^0.5.4: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + integrity sha512-4JD/Ivzg7PoW8NzdrBSr3UFwC9mHgvI7Z6z3QGBsSHgKaRTUDmyZAAKJo2UbG1kUVfS9WS8bi36N49U1xw43DA== json-schema-traverse@^0.4.1: version "0.4.1" @@ -2241,12 +1565,12 @@ json-schema-traverse@^0.4.1: json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -2255,21 +1579,6 @@ jstimezonedetect@^1.0.6: resolved "https://registry.yarnpkg.com/jstimezonedetect/-/jstimezonedetect-1.0.7.tgz#54bc13ff9960a6510288665cc9596244e21bd29d" integrity sha512-ARADHortktl9IZ1tr4GHwGPIAzgz3mLNCbR/YjWtRtc/O0o634O3NeFlpLjv95EvuDA5dc8z6yfgbS8nUc4zcQ== -keen-dataviz@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/keen-dataviz/-/keen-dataviz-1.2.1.tgz#6f7595a2051652e1bece2ce2296e47ffa5d79dd9" - integrity sha1-b3WVogUWUuG+ziziKW5H/6XXndk= - dependencies: - c3 "^0.4.18" - d3 "^3.5.17" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - knockout.validation@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/knockout.validation/-/knockout.validation-2.0.4.tgz#e87f82f41b5bdcb7029ea6be3fef2a903054558b" @@ -2278,140 +1587,55 @@ knockout.validation@^2.0.2: knockout@~3.4.2: version "3.4.2" resolved "https://registry.yarnpkg.com/knockout/-/knockout-3.4.2.tgz#e87958de77ad1e936f7ce645bab8b5d7c456d937" - integrity sha1-6HlY3netHpNvfOZFuri118RW2Tc= - -latest-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= - dependencies: - package-json "^4.0.0" + integrity sha512-yoY25btIjj8hLNd2HPF3Ld9fAf8idd/julcomODSdMX98C4pfODnWmPYmhnor9zh7cEAHpkMY04oLGKLXMqfvw== lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== dependencies: invert-kv "^1.0.0" -less-loader@~2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-2.2.3.tgz#b6d8f8139c8493df09d992a93a00734b08f84528" - integrity sha1-ttj4E5yEk98J2ZKpOgBzSwj4RSg= - dependencies: - loader-utils "^0.2.5" - less@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/less/-/less-4.1.2.tgz#6099ee584999750c2624b65f80145f8674e4b4b0" - integrity sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA== + version "4.6.4" + resolved "https://registry.yarnpkg.com/less/-/less-4.6.4.tgz#3ff8068e6c8a59f1ece8a6b9227bda28c1ed68a2" + integrity sha512-OJmO5+HxZLLw0RLzkqaNHzcgEAQG7C0y3aMbwtCzIUFZsLMNNq/1IdAdHEycQ58CwUO3jPTHmoN+tE5I7FQxNg== dependencies: - copy-anything "^2.0.1" + copy-anything "^3.0.5" parse-node-version "^1.0.1" - tslib "^2.3.0" optionalDependencies: errno "^0.1.1" graceful-fs "^4.1.2" image-size "~0.5.0" make-dir "^2.1.0" mime "^1.4.1" - needle "^2.5.2" + needle "^3.1.0" source-map "~0.6.0" -linkify-it@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" - integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== - dependencies: - uc.micro "^1.0.1" - linkifyjs@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-3.0.5.tgz#99e51a3a0c0e232fcb63ebb89eea3ff923378f34" integrity sha512-1Y9XQH65eQKA9p2xtk+zxvnTeQBG7rdAXSkUG97DmuI/Xhji9uaUzaWxRj6rf9YC0v8KKHkxav7tnLX82Sz5Fg== -listr-input@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/listr-input/-/listr-input-0.1.3.tgz#0c313967b6d179ebe964a81e9363ce2a5a39d25c" - integrity sha512-dvjSD1MrWGXxxPixpMQlSBmkyqhJrPxGo30un25k/vlvFOWZj70AauU+YkEh7CA8vmpkE6Wde37DJDmqYqF39g== - dependencies: - inquirer "^3.3.0" - rxjs "^5.5.2" - through "^2.3.8" - -listr-silent-renderer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" - integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= - -listr-update-renderer@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" - integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== - dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - elegant-spinner "^1.0.1" - figures "^1.7.0" - indent-string "^3.0.0" - log-symbols "^1.0.2" - log-update "^2.3.0" - strip-ansi "^3.0.1" - -listr-verbose-renderer@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" - integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== - dependencies: - chalk "^2.4.1" - cli-cursor "^2.1.0" - date-fns "^1.27.2" - figures "^2.0.0" - -listr@^0.14.1: - version "0.14.3" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" - integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== - dependencies: - "@samverschueren/stream-to-observable" "^0.3.0" - is-observable "^1.1.0" - is-promise "^2.1.0" - is-stream "^1.1.0" - listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.5.0" - listr-verbose-renderer "^0.5.0" - p-map "^2.0.0" - rxjs "^6.3.3" - load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + integrity sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ== dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" pify "^2.0.0" strip-bom "^3.0.0" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - loader-runner@^2.3.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@0.2.x, loader-utils@^0.2.16, loader-utils@^0.2.5: +loader-utils@0.2.x: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + integrity sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug== dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -2419,9 +1643,9 @@ loader-utils@0.2.x, loader-utils@^0.2.16, loader-utils@^0.2.5: object-assign "^4.0.1" loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -2430,12 +1654,12 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: loaders.css@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/loaders.css/-/loaders.css-0.1.2.tgz#3a9fb43726c73334a38142af9d0629019b658743" - integrity sha1-Op+0NybHMzSjgUKvnQYpAZtlh0M= + integrity sha512-Rhowlq24ey1VOeor+3wYOt9+MjaxBOJm1u4KlQgNC3+0xJ0LS4wq4iG57D/BPzvuD/7HHDGQOWJ+81oR2EI9bQ== locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -2443,105 +1667,47 @@ locate-path@^2.0.0: lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= - -lodash.chunk@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" - integrity sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw= + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== lodash.find@^4.3.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" - integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E= + integrity sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg== lodash.get@^4.2.1: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== lodash.has@^4.5.2: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" - integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI= + integrity sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g== lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" - integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= + integrity sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg== lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash.zip@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" - integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA= - -lodash@^4.17.14, lodash@^4.17.4, lodash@^4.3.0: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" - integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= - dependencies: - chalk "^1.0.0" - -log-symbols@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -log-update@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" - integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= - dependencies: - ansi-escapes "^3.0.0" - cli-cursor "^2.0.0" - wrap-ansi "^3.0.1" - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lodash@^4.17.14: + version "4.17.23" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.5" @@ -2566,41 +1732,15 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= - -markdown-it-ins-del@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/markdown-it-ins-del/-/markdown-it-ins-del-0.1.1.tgz#8b421d8e788ee84a1d572eb3fcc0028ce431c9ea" - integrity sha1-i0IdjniO6EodVy6z/MACjOQxyeo= - -markdown-it-sanitizer@~0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/markdown-it-sanitizer/-/markdown-it-sanitizer-0.4.3.tgz#2ba34e9fe16e6372ce7192fb50b37d9dfbff0102" - integrity sha1-K6NOn+FuY3LOcZL7ULN9nfv/AQI= - -markdown-it@~12.3.2: - version "12.3.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" - integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== - dependencies: - argparse "^2.0.1" - entities "~2.1.0" - linkify-it "^3.0.1" - mdurl "^1.0.1" - uc.micro "^1.0.5" - math-expression-evaluator@^1.2.14: - version "1.3.14" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.3.14.tgz#0ebeaccf65fea0f6f5a626f88df41814e5fcd9bf" - integrity sha512-M6AMrvq9bO8uL42KvQHPA2/SbAobA0R7gviUmPrcTcGfdwpaLitz4q2Euzx2lP9Oy88vxK3HOrsISgSwKsYS4A== + version "1.4.0" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.4.0.tgz#3d66031117fbb7b9715ea6c9c68c2cd2eebd37e2" + integrity sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== md5.js@^1.3.4: version "1.3.5" @@ -2611,46 +1751,21 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + integrity sha512-nOBDrc/wgpkd3X/JOhMqYR+/eLqlfLP4oQfoBA6QExIxEl+GU01oyEkwWyueyO8110pUKijtiHGhEmYoOn88oQ== dependencies: mimic-fn "^1.0.0" memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ== dependencies: errno "^0.1.3" readable-stream "^2.0.1" -meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" - miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -2659,23 +1774,11 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@~2.1.24: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -2693,11 +1796,6 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -2706,27 +1804,19 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" - integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== +minimatch@^3.1.1: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" -minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mississippi@^2.0.0: version "2.0.0" @@ -2747,24 +1837,24 @@ mississippi@^2.0.0: mithril@0.2.0, mithril@>=0.2: version "0.2.0" resolved "https://registry.yarnpkg.com/mithril/-/mithril-0.2.0.tgz#98e007699a15b243a26b3b522f61bee90fa5ffb9" - integrity sha1-mOAHaZoVskOiaztSL2G+6Q+l/7k= + integrity sha512-mp4pkyARLJmTyzuHJs8Q3Voh0Hg38n0HSmzQY1xhUKP9Hg+tLx5Dfzjf7Jlu9SWMCU9giZX/Xj4xsYFqjszSWA== mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" + minimist "^1.2.6" moment@^2.14.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + integrity sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ== dependencies: aproba "^1.1.1" copy-concurrently "^1.0.0" @@ -2773,39 +1863,18 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - -needle@^2.5.2: - version "2.9.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" - integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" +needle@^3.1.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-3.5.0.tgz#aa2023642cb41b11a11babb733fd8fa952919112" + integrity sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w== + dependencies: + iconv-lite "^0.6.3" sax "^1.2.4" -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== node-libs-browser@^2.0.0: version "2.2.1" @@ -2836,7 +1905,7 @@ node-libs-browser@^2.0.0: util "^0.11.0" vm-browserify "^1.0.1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -2849,121 +1918,78 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== normalize-url@^1.4.0: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= + integrity sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ== dependencies: object-assign "^4.0.1" prepend-http "^1.0.0" query-string "^4.1.0" sort-keys "^1.0.0" -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - -np@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/np/-/np-3.1.0.tgz#f83437459164c529fad801937c201488e319931d" - integrity sha512-3HTje97SzbsvK9g61C72PpDk9AloaaTn0K7xHbx7jMrs9vJtCZqu7TWUGxrcYGiKRO/uFRn5SiRZfYB/gpL9Iw== - dependencies: - "@samverschueren/stream-to-observable" "^0.3.0" - any-observable "^0.3.0" - chalk "^2.3.0" - del "^3.0.0" - execa "^0.10.0" - github-url-from-git "^1.5.0" - has-yarn "^1.0.0" - inquirer "^5.2.0" - is-scoped "^1.0.0" - issue-regex "^2.0.0" - listr "^0.14.1" - listr-input "^0.1.1" - log-symbols "^2.1.0" - meow "^5.0.0" - npm-name "^5.0.0" - p-timeout "^2.0.1" - read-pkg-up "^3.0.0" - rxjs "^6.2.0" - semver "^5.2.0" - split "^1.0.0" - terminal-link "^1.1.0" - update-notifier "^2.1.0" - -npm-name@^5.0.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/npm-name/-/npm-name-5.5.0.tgz#3a73adbcb0488a41a44ff820ed51dcc32c72bd09" - integrity sha512-l7/uyVfEi2e3ho+ovaJZC0xlbwzXNUz3RxkxpfcnLuoGKAuYoo9YoJ/uy18PsTD8IziugGHks4t/mGmBJEZ4Qg== - dependencies: - got "^9.6.0" - is-scoped "^2.1.0" - is-url-superb "^3.0.0" - lodash.zip "^4.2.0" - registry-auth-token "^4.0.0" - registry-url "^5.1.0" - validate-npm-package-name "^3.0.0" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== dependencies: path-key "^2.0.0" num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg== number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= + integrity sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ== object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: - ee-first "1.1.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== os-locale@^2.0.0: version "2.1.0" @@ -2972,22 +1998,12 @@ os-locale@^2.0.0: dependencies: execa "^0.7.0" lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + mem "^1.1.0" p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-limit@^1.1.0: version "1.3.0" @@ -2999,41 +2015,14 @@ p-limit@^1.1.0: p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-timeout@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" - integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== - dependencies: - p-finally "^1.0.0" - p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -package-json@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" - integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= - dependencies: - got "^6.7.1" - registry-auth-token "^3.0.1" - registry-url "^3.0.3" - semver "^5.1.0" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== pako@~1.0.5: version "1.0.11" @@ -3049,32 +2038,24 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== +parse-asn1@^5.0.0, parse-asn1@^5.1.9: + version "5.1.9" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.9.tgz#8dd24c3ea8da77dffbc708d94eaf232fd6156e95" + integrity sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg== dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + pbkdf2 "^3.1.5" + safe-buffer "^5.2.1" parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== dependencies: error-ex "^1.2.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-node-version@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" @@ -3085,32 +2066,20 @@ path-browserify@0.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^2.0.0, path-key@^2.0.1: +path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== path-parse@^1.0.7: version "1.0.7" @@ -3120,37 +2089,31 @@ path-parse@^1.0.7: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + integrity sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ== dependencies: pify "^2.0.0" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== +pbkdf2@^3.1.2, pbkdf2@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.5.tgz#444a59d7a259a95536c56e80c89de31cc01ed366" + integrity sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ== dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" + create-hash "^1.2.0" + create-hmac "^1.1.7" + ripemd160 "^2.0.3" + safe-buffer "^5.2.1" + sha.js "^2.4.12" + to-buffer "^1.2.1" pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== pify@^4.0.1: version "4.0.1" @@ -3162,41 +2125,22 @@ pikaday@^1.3.2: resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.8.2.tgz#72cc73fab7ccc068cbdf7dcaa1ce400fcfd894e3" integrity sha512-TNtsE+34BIax3WtkB/qqu5uepV1McKYEgvL3kWzU7aqPCpMEN6rBF3AOwu4WCwAealWlBGobXny/9kJb49C1ew== -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= - dependencies: - find-up "^1.0.0" - pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + integrity sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw== dependencies: find-up "^2.1.0" -popper.js@^1.16.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== postcss-calc@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" - integrity sha1-d7rnypKK2FcW4v2kLyYb98HWW14= + integrity sha512-iBcptYFq+QUh9gzP7ta2btw50o40s4uLI4UDVgd5yRAZtUDWc5APdl5yQDd2h/TyiZNbJrv0HiYhT102CMgN7Q== dependencies: postcss "^5.0.2" postcss-message-helpers "^2.0.0" @@ -3205,7 +2149,7 @@ postcss-calc@^5.2.0: postcss-colormin@^2.1.8: version "2.2.2" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" - integrity sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks= + integrity sha512-XXitQe+jNNPf+vxvQXIQ1+pvdQKWKgkx8zlJNltcMEmLma1ypDRDQwlLt+6cP26fBreihNhZxohh1rcgCH2W5w== dependencies: colormin "^1.0.5" postcss "^5.0.13" @@ -3214,7 +2158,7 @@ postcss-colormin@^2.1.8: postcss-convert-values@^2.3.4: version "2.6.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" - integrity sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0= + integrity sha512-SE7mf25D3ORUEXpu3WUqQqy0nCbMuM5BEny+ULE/FXdS/0UMA58OdzwvzuHJRpIFlk1uojt16JhaEogtP6W2oA== dependencies: postcss "^5.0.11" postcss-value-parser "^3.1.2" @@ -3222,35 +2166,35 @@ postcss-convert-values@^2.3.4: postcss-discard-comments@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" - integrity sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0= + integrity sha512-yGbyBDo5FxsImE90LD8C87vgnNlweQkODMkUZlDVM/CBgLr9C5RasLGJxxh9GjVOBeG8NcCMatoqI1pXg8JNXg== dependencies: postcss "^5.0.14" postcss-discard-duplicates@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" - integrity sha1-uavye4isGIFYpesSq8riAmO5GTI= + integrity sha512-+lk5W1uqO8qIUTET+UETgj9GWykLC3LOldr7EehmymV0Wu36kyoHimC4cILrAAYpHQ+fr4ypKcWcVNaGzm0reA== dependencies: postcss "^5.0.4" postcss-discard-empty@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" - integrity sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU= + integrity sha512-IBFoyrwk52dhF+5z/ZAbzq5Jy7Wq0aLUsOn69JNS+7YeuyHaNzJwBIYE0QlUH/p5d3L+OON72Fsexyb7OK/3og== dependencies: postcss "^5.0.14" postcss-discard-overridden@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" - integrity sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg= + integrity sha512-IyKoDL8QNObOiUc6eBw8kMxBHCfxUaERYTUe2QF8k7j/xiirayDzzkmlR6lMQjrAM1p1DDRTvWrS7Aa8lp6/uA== dependencies: postcss "^5.0.16" postcss-discard-unused@^2.2.1: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" - integrity sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM= + integrity sha512-nCbFNfqYAbKCw9J6PSJubpN9asnrwVLkRDFc4KCwyUEdOtM5XDE/eTW3OpqHrYY1L4fZxgan7LLRAAYYBzwzrg== dependencies: postcss "^5.0.14" uniqs "^2.0.0" @@ -3265,7 +2209,7 @@ postcss-filter-plugins@^2.0.0: postcss-merge-idents@^2.1.5: version "2.1.7" resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" - integrity sha1-TFUwMTwI4dWzu/PSu8dH4njuonA= + integrity sha512-9DHmfCZ7/hNHhIKnNkz4CU0ejtGen5BbTRJc13Z2uHfCedeCUsK2WEQoAJRBL+phs68iWK6Qf8Jze71anuysWA== dependencies: has "^1.0.1" postcss "^5.0.10" @@ -3274,14 +2218,14 @@ postcss-merge-idents@^2.1.5: postcss-merge-longhand@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" - integrity sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg= + integrity sha512-ma7YvxjdLQdifnc1HFsW/AW6fVfubGyR+X4bE3FOSdBVMY9bZjKVdklHT+odknKBB7FSCfKIHC3yHK7RUAqRPg== dependencies: postcss "^5.0.4" postcss-merge-rules@^2.0.3: version "2.1.2" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" - integrity sha1-0d9d+qexrMO+VT8OnhDofGG19yE= + integrity sha512-Wgg2FS6W3AYBl+5L9poL6ZUISi5YzL+sDCJfM7zNw/Q1qsyVQXXZ2cbVui6mu2cYJpt1hOKCGj1xA4mq/obz/Q== dependencies: browserslist "^1.5.2" caniuse-api "^1.5.2" @@ -3292,12 +2236,12 @@ postcss-merge-rules@^2.0.3: postcss-message-helpers@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= + integrity sha512-tPLZzVAiIJp46TBbpXtrUAKqedXSyW5xDEo1sikrfEfnTs+49SBZR/xDdqCiJvSSbtr615xDsaMF3RrxS2jZlA== postcss-minify-font-values@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" - integrity sha1-S1jttWZB66fIR0qzUmyv17vey2k= + integrity sha512-vFSPzrJhNe6/8McOLU13XIsERohBJiIFFuC1PolgajOZdRWqRgKITP/A4Z/n4GQhEmtbxmO9NDw3QLaFfE1dFQ== dependencies: object-assign "^4.0.1" postcss "^5.0.4" @@ -3306,7 +2250,7 @@ postcss-minify-font-values@^1.0.2: postcss-minify-gradients@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" - integrity sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE= + integrity sha512-DZhT0OE+RbVqVyGsTIKx84rU/5cury1jmwPa19bViqYPQu499ZU831yMzzsyC8EhiZVd73+h5Z9xb/DdaBpw7Q== dependencies: postcss "^5.0.12" postcss-value-parser "^3.3.0" @@ -3314,7 +2258,7 @@ postcss-minify-gradients@^1.0.1: postcss-minify-params@^1.0.4: version "1.2.2" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" - integrity sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM= + integrity sha512-hhJdMVgP8vasrHbkKAk+ab28vEmPYgyuDzRl31V3BEB3QOR3L5TTIVEWLDNnZZ3+fiTi9d6Ker8GM8S1h8p2Ow== dependencies: alphanum-sort "^1.0.1" postcss "^5.0.2" @@ -3324,7 +2268,7 @@ postcss-minify-params@^1.0.4: postcss-minify-selectors@^2.0.4: version "2.1.1" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" - integrity sha1-ssapjAByz5G5MtGkllCBFDEXNb8= + integrity sha512-e13vxPBSo3ZaPne43KVgM+UETkx3Bs4/Qvm6yXI9HQpQp4nyb7HZ0gKpkF+Wn2x+/dbQ+swNpCdZSbMOT7+TIA== dependencies: alphanum-sort "^1.0.2" has "^1.0.1" @@ -3341,7 +2285,7 @@ postcss-modules-extract-imports@^1.2.0: postcss-modules-local-by-default@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" - integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= + integrity sha512-X4cquUPIaAd86raVrBwO8fwRfkIdbwFu7CTfEOjiZQHVQwlHRSkTgH5NLDmMm5+1hQO8u6dZ+TOOJDbay1hYpA== dependencies: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" @@ -3349,7 +2293,7 @@ postcss-modules-local-by-default@^1.2.0: postcss-modules-scope@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" - integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= + integrity sha512-LTYwnA4C1He1BKZXIx1CYiHixdSe9LWYVKadq9lK5aCCMkoOkFyZ7aigt+srfjlRplJY3gIol6KUNefdMQJdlw== dependencies: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" @@ -3357,7 +2301,7 @@ postcss-modules-scope@^1.1.0: postcss-modules-values@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" - integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= + integrity sha512-i7IFaR9hlQ6/0UgFuqM6YWaCfA1Ej8WMg8A5DggnH1UGKJvTV/ugqq/KaULixzzOi3T/tF6ClBXcHGCzdd5unA== dependencies: icss-replace-symbols "^1.1.0" postcss "^6.0.1" @@ -3365,14 +2309,14 @@ postcss-modules-values@^1.3.0: postcss-normalize-charset@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" - integrity sha1-757nEhLX/nWceO0WL2HtYrXLk/E= + integrity sha512-RKgjEks83l8w4yEhztOwNZ+nLSrJ+NvPNhpS+mVDzoaiRHZQVoG7NF2TP5qjwnaN9YswUhj6m1E0S0Z+WDCgEQ== dependencies: postcss "^5.0.5" postcss-normalize-url@^3.0.7: version "3.0.8" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" - integrity sha1-EI90s/L82viRov+j6kWSJ5/HgiI= + integrity sha512-WqtWG6GV2nELsQEFES0RzfL2ebVwmGl/M8VmMbshKto/UClBo+mznX8Zi4/hkThdqx7ijwv+O8HWPdpK7nH/Ig== dependencies: is-absolute-url "^2.0.0" normalize-url "^1.4.0" @@ -3382,7 +2326,7 @@ postcss-normalize-url@^3.0.7: postcss-ordered-values@^2.1.0: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" - integrity sha1-7sbCpntsQSqNsgQud/6NpD+VwR0= + integrity sha512-5RB1IUZhkxDCfa5fx/ogp/A82mtq+r7USqS+7zt0e428HJ7+BHCxyeY39ClmkkUtxdOd3mk8gD6d9bjH2BECMg== dependencies: postcss "^5.0.4" postcss-value-parser "^3.0.1" @@ -3390,7 +2334,7 @@ postcss-ordered-values@^2.1.0: postcss-reduce-idents@^2.2.2: version "2.4.0" resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" - integrity sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM= + integrity sha512-0+Ow9e8JLtffjumJJFPqvN4qAvokVbdQPnijUDSOX8tfTwrILLP4ETvrZcXZxAtpFLh/U0c+q8oRMJLr1Kiu4w== dependencies: postcss "^5.0.4" postcss-value-parser "^3.0.2" @@ -3398,14 +2342,14 @@ postcss-reduce-idents@^2.2.2: postcss-reduce-initial@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" - integrity sha1-aPgGlfBF0IJjqHmtJA343WT2ROo= + integrity sha512-jJFrV1vWOPCQsIVitawGesRgMgunbclERQ/IRGW7r93uHrVzNQQmHQ7znsOIjJPZ4yWMzs5A8NFhp3AkPHPbDA== dependencies: postcss "^5.0.4" postcss-reduce-transforms@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" - integrity sha1-/3b02CEkN7McKYpC0uFEQCV3GuE= + integrity sha512-lGgRqnSuAR5i5uUg1TA33r9UngfTadWxOyL2qx1KuPoCQzfmtaHjp9PuwX7yVyRxG3BWBzeFUaS5uV9eVgnEgQ== dependencies: has "^1.0.1" postcss "^5.0.8" @@ -3414,7 +2358,7 @@ postcss-reduce-transforms@^1.0.3: postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= + integrity sha512-3pqyakeGhrO0BQ5+/tGTfvi5IAUAhHRayGK8WFSu06aEv2BmHoXw/Mhb+w7VY5HERIuC+QoUI7wgrCcq2hqCVA== dependencies: flatten "^1.0.2" indexes-of "^1.0.1" @@ -3423,7 +2367,7 @@ postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: postcss-svgo@^2.1.1: version "2.1.6" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" - integrity sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0= + integrity sha512-y5AdQdgBoF4rbpdbeWAJuxE953g/ylRfVNp6mvAi61VCN/Y25Tu9p5mh3CyI42WbTRIiwR9a1GdFtmDnNPeskQ== dependencies: is-svg "^2.0.0" postcss "^5.0.14" @@ -3433,7 +2377,7 @@ postcss-svgo@^2.1.1: postcss-unique-selectors@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" - integrity sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0= + integrity sha512-WZX8r1M0+IyljoJOJleg3kYm10hxNYF9scqAT7v/xeSX1IdehutOM85SNO0gP9K+bgs86XERr7Ud5u3ch4+D8g== dependencies: alphanum-sort "^1.0.1" postcss "^5.0.4" @@ -3447,7 +2391,7 @@ postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^ postcss-zindex@^2.0.1: version "2.2.0" resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" - integrity sha1-0hCd3AVbka9n/EyzsCWUZjnSryI= + integrity sha512-uhRZ2hRgj0lorxm9cr62B01YzpUe63h0RXMXQ4gWW3oa2rpJh+FJAiEAytaFCPU/VgaBS+uW2SJ1XKyDNz1h4w== dependencies: has "^1.0.1" postcss "^5.0.4" @@ -3472,25 +2416,10 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^5.4.0" -prepend-http@^1.0.0, prepend-http@^1.0.1: +prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -pretty-data@^0.40.0: - version "0.40.0" - resolved "https://registry.yarnpkg.com/pretty-data/-/pretty-data-0.40.0.tgz#572aa8ea23467467ab94b6b5266a6fd9c8fddd72" - integrity sha1-Vyqo6iNGdGerlLa1Jmpv2cj93XI= - -private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg== process-nextick-args@~2.0.0: version "2.0.1" @@ -3500,24 +2429,24 @@ process-nextick-args@~2.0.0: process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== -public-encrypt@^4.0.0: +public-encrypt@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== @@ -3537,14 +2466,6 @@ pump@^2.0.0, pump@^2.0.1: end-of-stream "^1.1.0" once "^1.3.1" -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pumpify@^1.3.3: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" @@ -3554,35 +2475,32 @@ pumpify@^1.3.3: inherits "^2.0.3" pump "^2.0.0" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4: +punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qs@6.9.7: - version "6.9.7" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" - integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== +qs@^6.12.3: + version "6.15.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.0.tgz#db8fd5d1b1d2d6b5b33adaf87429805f1909e7b3" + integrity sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ== + dependencies: + side-channel "^1.1.0" query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= + integrity sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q== dependencies: object-assign "^4.1.0" strict-uri-encode "^1.0.0" @@ -3590,26 +2508,16 @@ query-string@^4.1.0: querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== -quick-lru@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3: +randomfill@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== @@ -3617,69 +2525,32 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -raw-body@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" - integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== - dependencies: - bytes "3.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-loader@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa" - integrity sha1-DD0L6u2KAclm2Xh793goElKpeao= - -rc@^1.0.1, rc@^1.1.6, rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" + integrity sha512-sf7oGoLuaYAScB4VGr0tzetsYlS8EJH6qnTCfQ/WVEa89hALQ4RQfCKt5xCyPQKPDUbVUAIP1QsxAwfAjlDp7Q== read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + integrity sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w== dependencies: find-up "^2.0.0" read-pkg "^2.0.0" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + integrity sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA== dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" path-type "^2.0.0" -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.8, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -3689,27 +2560,10 @@ read-pkg@^3.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -redent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= - dependencies: - indent-string "^3.0.0" - strip-indent "^2.0.0" - reduce-css-calc@^1.2.6: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= + integrity sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA== dependencies: balanced-match "^0.4.2" math-expression-evaluator "^1.2.14" @@ -3722,135 +2576,48 @@ reduce-function-call@^1.0.1: dependencies: balanced-match "^1.0.0" -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -registry-auth-token@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" - integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A== - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== - dependencies: - rc "^1.2.8" - -registry-url@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= - dependencies: - rc "^1.0.1" - -registry-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== resolve@^1.10.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2: +rimraf@^2.5.4, rimraf@^2.6.2: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== +ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.3.tgz#9be54e4ba5e3559c8eee06a25cd7648bbccdf5a8" + integrity sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA== dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -run-async@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + hash-base "^3.1.2" + inherits "^2.0.4" run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + integrity sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg== dependencies: aproba "^1.1.1" -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= - -rxjs@^5.5.2: - version "5.5.12" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" - integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== - dependencies: - symbol-observable "1.0.1" - -rxjs@^6.2.0, rxjs@^6.3.3: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3860,12 +2627,17 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@^1.2.4, sax@~1.2.1: +sax@^1.2.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.6.0.tgz#da59637629307b97e7c4cb28e080a7bc38560d5b" + integrity sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA== + +sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -3873,7 +2645,7 @@ sax@^1.2.4, sax@~1.2.1: schema-utils@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" - integrity sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8= + integrity sha512-QaVYBaD9U8scJw2EBWnCBY+LJ0AD+/2edTaigDs0XLDLBfJmSUK9KGqktg1rb32U3z4j/XwvFwHHH1YfbYFd7Q== dependencies: ajv "^5.0.0" @@ -3894,32 +2666,15 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -scoped-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" - integrity sha1-o0a7Gs1CB65wvXwMfKnlZra63bg= - -scoped-regex@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-2.1.0.tgz#7b9be845d81fd9d21d1ec97c61a0b7cf86d2015f" - integrity sha512-g3WxHrqSWCZHGHlSrF51VXFdjImhwvH8ZO/pryFH56Qi0cDsZfylQa/t0jCzVQFNbNvM00HfHjkDPEuarKDSWQ== - select2@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/select2/-/select2-3.5.1.tgz#f2819489bbc65fd6d328be72bbe2b95dd7e87cfe" - integrity sha1-8oGUibvGX9bTKL5yu+K5XdfofP4= + integrity sha512-IFX3UFPpPyK1I1Kuw1R1x+upMyNAZbMlkFhiTnRCRR7ii0KU1brmJMLa3GZcrMWCHiQlm0eKqb6i4XO4pqOrGQ== -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= - dependencies: - semver "^5.0.3" - -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.2.0, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +"semver@2 || 3 || 4 || 5", semver@^5.6.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== serialize-javascript@^1.4.0: version "1.9.1" @@ -3929,57 +2684,95 @@ serialize-javascript@^1.4.0: set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" setimmediate@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== +sha.js@^2.4.0, sha.js@^2.4.12, sha.js@^2.4.8: + version "2.4.12" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" + integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" -signal-exit@^3.0.0, signal-exit@^3.0.2: +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^3.0.0: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= - sort-keys@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= + integrity sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg== dependencies: is-plain-obj "^1.0.0" @@ -3988,24 +2781,17 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map@0.1.x: version "0.1.43" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= + integrity sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ== dependencies: amdefine ">=0.0.4" -source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: +source-map@^0.5.3, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" @@ -4013,17 +2799,17 @@ source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -4034,21 +2820,14 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" + version "3.0.23" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz#b069e687b1291a32f126893ed76a27a745ee2133" + integrity sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== ssri@^5.2.4: version "5.3.0" @@ -4057,11 +2836,6 @@ ssri@^5.2.4: dependencies: safe-buffer "^5.1.1" -"statuses@>= 1.5.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -4090,25 +2864,25 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +string-width@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -4116,7 +2890,7 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -4133,38 +2907,28 @@ string_decoder@~1.1.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== -style-loader@^0.23.1, style-loader@~0.13.1: +style-loader@^0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg== @@ -4175,37 +2939,29 @@ style-loader@^0.23.1, style-loader@~0.13.1: supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== dependencies: has-flag "^1.0.0" supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= + integrity sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw== dependencies: has-flag "^2.0.0" -supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-hyperlinks@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" - integrity sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw== - dependencies: - has-flag "^2.0.0" - supports-color "^5.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -4214,7 +2970,7 @@ supports-preserve-symlinks-flag@^1.0.0: svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" - integrity sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U= + integrity sha512-jT/g9FFMoe9lu2IT6HtAxTA7RR2XOrmcrmCtGnyB/+GQnV6ZjNn+KOHZbZ35yL81+1F/aB6OeEsJztzBQ2EEwA== dependencies: coa "~1.0.1" colors "~1.1.2" @@ -4224,36 +2980,11 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= - -symbol-observable@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - tapable@^0.2.7: version "0.2.9" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8" integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= - dependencies: - execa "^0.7.0" - -terminal-link@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-1.3.0.tgz#3e9a308289e13340053aaf40e8f1a06d1335646e" - integrity sha512-nFaWG/gs3brGi3opgWU2+dyFGbQ7tueSRYOBOD8URdDXCbAGqDEZzuskCc+okCClYcJFDPwn8e2mbv4FqAnWFA== - dependencies: - ansi-escapes "^3.2.0" - supports-hyperlinks "^1.0.1" - through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -4262,16 +2993,6 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@2, through@^2.3.6, through@^2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -timed-out@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - timers-browserify@^2.0.4: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" @@ -4279,37 +3000,19 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" -tlds@^1.203.0: - version "1.229.0" - resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.229.0.tgz#fd02585a234669d47a7f1752c87f100a34feba60" - integrity sha512-yZCodKInN+BPGUyYgKHsodJ2FVWRjW/fYx6rKCAT/e24BBJd8FcxWgKD0aBgk+7uQ/88h/fmRTd4Nvzxf3313A== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +to-buffer@^1.2.0, to-buffer@^1.2.1, to-buffer@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.2.tgz#ffe59ef7522ada0a2d1cb5dfe03bb8abc3cdc133" + integrity sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw== + dependencies: + isarray "^2.0.5" + safe-buffer "^5.2.1" + typed-array-buffer "^1.0.3" "treebeard@https://github.com/CenterForOpenScience/treebeard.git#d2bb8f6f8104fcac040402727f431c26722b269e": version "0.6.1" @@ -4320,65 +3023,36 @@ toidentifier@1.0.1: jquery-ui ">=1.10.4" mithril ">=0.2" -trim-newlines@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -tslib@^1.9.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== -type@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.6.0.tgz#3ca6099af5981d36ca86b78442973694278a219f" - integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== typeahead.js@^0.11.1: version "0.11.1" resolved "https://registry.yarnpkg.com/typeahead.js/-/typeahead.js-0.11.1.tgz#4e64e671b22310a8606f4aec805924ba84b015b8" - integrity sha1-TmTmcbIjEKhgb0rsgFkkuoSwFbg= + integrity sha512-yGaLzGjVHyryZdNfrWz2NHXUwEO7hrlVmGMGCo5+6mH3nEEhcQ0Te3mK3G60uRnxfERu8twOWSU4WmwScbwhMg== dependencies: jquery ">=1.7" +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== uglify-es@^3.3.4: version "3.3.9" @@ -4405,12 +3079,12 @@ uglifyjs-webpack-plugin@1.3.0, uglifyjs-webpack-plugin@^0.4.6: uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + integrity sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ== unique-filename@^1.1.0: version "1.1.1" @@ -4426,39 +3100,6 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= - dependencies: - crypto-random-string "^1.0.0" - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= - -update-notifier@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" - integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== - dependencies: - boxen "^1.2.1" - chalk "^2.0.1" - configstore "^3.0.0" - import-lazy "^2.1.0" - is-ci "^1.0.10" - is-installed-globally "^0.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4475,47 +3116,25 @@ url-loader@~0.6.2: mime "^1.4.1" schema-utils "^0.3.0" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-5.0.0.tgz#8f5456ab83d898d18b2f91753a702649b873273a" - integrity sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g== - dependencies: - ip-regex "^4.1.0" - tlds "^1.203.0" - url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + version "0.11.4" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" + integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== dependencies: - punycode "1.3.2" - querystring "0.2.0" + punycode "^1.4.1" + qs "^6.12.3" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= +util@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: - inherits "2.0.1" + inherits "2.0.3" util@^0.11.0: version "0.11.1" @@ -4524,11 +3143,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -4537,13 +3151,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= - dependencies: - builtins "^1.0.3" - vendors@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" @@ -4555,9 +3162,9 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== watchpack@^1.4.0, watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== + version "2.5.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.1.tgz#dd38b601f669e0cbf567cb802e75cead82cde102" + integrity sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -4601,12 +3208,25 @@ webpack@3.12.0: whet.extend@~0.9.9: version "0.9.9" resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= + integrity sha512-mmIPAft2vTgEILgPeZFqE/wWh24SEsR/k+N9fJ3Jxrz44iDFy9aemCxdksfURSHYFCLmvs/d/7Iso5XjPpNfrA== which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.16: + version "1.1.20" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" + integrity sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" which@^1.2.9: version "1.3.1" @@ -4615,13 +3235,6 @@ which@^1.2.9: dependencies: isexe "^2.0.0" -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== - dependencies: - string-width "^2.1.1" - worker-farm@^1.5.2: version "1.7.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" @@ -4632,37 +3245,15 @@ worker-farm@^1.5.2: wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" -wrap-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" - integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^2.0.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" @@ -4682,26 +3273,19 @@ y18n@^4.0.0: yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yargs-parser@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= + integrity sha512-WhzC+xgstid9MbVUktco/bf+KJG+Uu6vMX0LN1sLJvwmbCQVxb4D8LzogobonKycNasCZLdOzTAk1SK7+K7swg== dependencies: camelcase "^4.1.0" yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= + integrity sha512-3RiZrpLpjrzIAKgGdPktBcMP/eG5bDFlkI+PHle1qwzyVXyDQL+pD/eZaMoOOO0Y7LLBfjpucObuUm/icvbpKQ== dependencies: camelcase "^4.1.0" cliui "^3.2.0" @@ -4720,4 +3304,4 @@ yargs@^8.0.2: zxcvbn@^4.2.0: version "4.4.2" resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30" - integrity sha1-KOwXzwl0PtyrBW3dixsGJizHPDA= + integrity sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==

Copyright © 2025 Center For Open Science, All rights reserved. | Privacy Policy

-

210 Ridge McIntire Road, Suite 500, Charlottesville, VA 22903-5083

Copyright © 2025 Center For Open Science, All rights reserved. | Privacy Policy

-

210 Ridge McIntire Road, Suite 500, Charlottesville, VA 22903-5083