diff --git a/swh/web/assets/src/bundles/browse/origin-save.js b/swh/web/assets/src/bundles/browse/origin-save.js
index 871038d1..c1578c14 100644
--- a/swh/web/assets/src/bundles/browse/origin-save.js
+++ b/swh/web/assets/src/bundles/browse/origin-save.js
@@ -1,265 +1,299 @@
/**
* Copyright (C) 2018-2019 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
*/
import {handleFetchError, csrfPost, isGitRepoUrl, removeUrlFragment} from 'utils/functions';
import {validate} from 'validate.js';
let saveRequestsTable;
function originSaveRequest(originType, originUrl,
acceptedCallback, pendingCallback, errorCallback) {
let addSaveOriginRequestUrl = Urls.browse_origin_save_request(originType, originUrl);
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
$('.swh-processing-save-request').css('display', 'block');
csrfPost(addSaveOriginRequestUrl, headers)
.then(handleFetchError)
.then(response => response.json())
.then(data => {
$('.swh-processing-save-request').css('display', 'none');
if (data.save_request_status === 'accepted') {
acceptedCallback();
} else {
pendingCallback();
}
})
.catch(response => {
$('.swh-processing-save-request').css('display', 'none');
- if (response.status === 403) {
- errorCallback();
- }
+ errorCallback(response.status);
});
}
+function htmlAlert(type, message) {
+ return `
- The "save code now" request has been accepted and will be processed as soon as possible.
-
`;
+ let saveRequestAcceptedAlert = htmlAlert(
+ 'success',
+ 'The "save code now" request has been accepted and will be processed as soon as possible.'
+ );
+
+ let saveRequestPendingAlert = htmlAlert(
+ 'warning',
+ 'The "save code now" request has been put in pending state and may be accepted for processing after manual review.'
+ );
- let saveRequestPendingAlert =
- `
- The "save code now" request has been put in pending state and may be accepted for processing after manual review.
-
`;
+ let saveRequestRejectedAlert = htmlAlert(
+ 'danger',
+ 'The "save code now" request has been rejected because the provided origin url is blacklisted.'
+ );
- let saveRequestRejectedAlert =
- `
- The "save code now" request has been rejected because the provided origin url is blacklisted.
-
`;
+ let saveRequestRateLimitedAlert = htmlAlert(
+ 'danger',
+ 'The rate limit for "save code now" requests has been reached. Please try again later.'
+ );
+
+ let saveRequestUnknownErrorAlert = htmlAlert(
+ 'danger',
+ 'An unexpected error happened when submitting the "save code now request'
+ );
$('#swh-save-origin-form').submit(event => {
event.preventDefault();
event.stopPropagation();
$('.alert').alert('close');
if (event.target.checkValidity()) {
$(event.target).removeClass('was-validated');
let originType = $('#swh-input-origin-type').val();
let originUrl = $('#swh-input-origin-url').val();
originSaveRequest(originType, originUrl,
() => $('#swh-origin-save-request-status').html(saveRequestAcceptedAlert),
() => $('#swh-origin-save-request-status').html(saveRequestPendingAlert),
- () => {
+ (statusCode) => {
$('#swh-origin-save-request-status').css('color', 'red');
- $('#swh-origin-save-request-status').html(saveRequestRejectedAlert);
+ if (statusCode === 403) {
+ $('#swh-origin-save-request-status').html(saveRequestRejectedAlert);
+ } else if (statusCode === 429) {
+ $('#swh-origin-save-request-status').html(saveRequestRateLimitedAlert);
+ } else {
+ $('#swh-origin-save-request-status').html(saveRequestUnknownErrorAlert);
+ }
});
} else {
$(event.target).addClass('was-validated');
}
});
$('#swh-show-origin-save-requests-list').on('click', (event) => {
event.preventDefault();
$('.nav-tabs a[href="#swh-origin-save-requests-list"]').tab('show');
});
$('#swh-input-origin-url').on('input', function(event) {
let originUrl = $(this).val().trim();
$(this).val(originUrl);
$('#swh-input-origin-type option').each(function() {
let val = $(this).val();
if (val && originUrl.includes(val)) {
$(this).prop('selected', true);
}
});
});
if (window.location.hash === '#requests') {
$('.nav-tabs a[href="#swh-origin-save-requests-list"]').tab('show');
}
});
}
export function validateSaveOriginUrl(input) {
let originUrl = input.value.trim();
let validUrl = validate({website: originUrl}, {
website: {
url: {
schemes: ['http', 'https', 'svn', 'git']
}
}
}) === undefined;
let originType = $('#swh-input-origin-type').val();
if (originType === 'git' && validUrl) {
// additional checks for well known code hosting providers
let githubIdx = originUrl.indexOf('://github.com');
let gitlabIdx = originUrl.indexOf('://gitlab.');
let gitSfIdx = originUrl.indexOf('://git.code.sf.net');
let bitbucketIdx = originUrl.indexOf('://bitbucket.org');
if (githubIdx !== -1 && githubIdx <= 5) {
validUrl = isGitRepoUrl(originUrl, 'github.com');
} else if (gitlabIdx !== -1 && gitlabIdx <= 5) {
let startIdx = gitlabIdx + 3;
let idx = originUrl.indexOf('/', startIdx);
if (idx !== -1) {
let gitlabDomain = originUrl.substr(startIdx, idx - startIdx);
// GitLab repo url needs to be suffixed by '.git' in order to be successfully loaded
// This is due to a bug in dulwich < 0.19.11.
// TODO: remove this check once dulwich >= 0.19.11 is used in production
validUrl = isGitRepoUrl(originUrl, gitlabDomain) && originUrl.endsWith('.git');
} else {
validUrl = false;
}
} else if (gitSfIdx !== -1 && gitSfIdx <= 5) {
validUrl = isGitRepoUrl(originUrl, 'git.code.sf.net/p');
} else if (bitbucketIdx !== -1 && bitbucketIdx <= 5) {
validUrl = isGitRepoUrl(originUrl, 'bitbucket.org');
}
}
if (validUrl) {
input.setCustomValidity('');
} else {
input.setCustomValidity('The origin url is not valid or does not reference a code repository');
}
}
export function initTakeNewSnapshot() {
- let newSnapshotRequestAcceptedAlert =
- `
- The "take new snapshot" request has been accepted and will be processed as soon as possible.
-
`;
+ let newSnapshotRequestAcceptedAlert = htmlAlert(
+ 'success',
+ 'The "take new snapshot" request has been accepted and will be processed as soon as possible.'
+ );
+
+ let newSnapshotRequestPendingAlert = htmlAlert(
+ 'warning',
+ 'The "take new snapshot" request has been put in pending state and may be accepted for processing after manual review.'
+ );
+
+ let newSnapshotRequestRejectedAlert = htmlAlert(
+ 'danger',
+ 'The "take new snapshot" request has been rejected.'
+ );
- let newSnapshotRequestPendingAlert =
- `
- The "take new snapshot" request has been put in pending state and may be accepted for processing after manual review.
-
`;
+ let newSnapshotRequestRateLimitAlert = htmlAlert(
+ 'danger',
+ 'The rate limit for "take new snapshot" requests has been reached. Please try again later.'
+ );
- let newSnapshotRequestRejectedAlert =
- `
- The "take new snapshot" request has been rejected.
-