Merge pull request #99 from lbryio/client-side-name-validation
Client side name validation
This commit is contained in:
commit
324b4f5e78
5 changed files with 130 additions and 160 deletions
|
@ -24,11 +24,10 @@ module.exports = {
|
|||
default:
|
||||
throw new Error('The ' + file.Type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');
|
||||
}
|
||||
|
||||
// validate name
|
||||
// validate claim name
|
||||
const invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||
if (invalidCharacters) {
|
||||
throw new Error('The name you provided is not allowed. Please use A-Z, a-z, 0-9, and "-" only.');
|
||||
throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"');
|
||||
}
|
||||
// validate license
|
||||
if ((license.indexOf('Public Domain') === -1) && (license.indexOf('Creative Commons') === -1)) {
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
// define variables
|
||||
var socket = io();
|
||||
var uploader = new SocketIOFileUpload(socket);
|
||||
var stagedFiles = null;
|
||||
|
||||
/* configure the submit button */
|
||||
function publishSelectedImage(event) {
|
||||
event.preventDefault();
|
||||
// validate inputs
|
||||
var name = document.getElementById('publish-name').value;
|
||||
try {
|
||||
validateSubmission(stagedFiles, name);
|
||||
} catch (error) {
|
||||
if (error.name === 'FileError'){
|
||||
showError('input-error-file-selection', error.message);
|
||||
} else if (error.name === 'NameError') {
|
||||
showError('input-error-claim-name', error.message);
|
||||
} else {
|
||||
showError('input-error-publish-submit', error.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// make sure the name is available then start the upload
|
||||
validateClaimName(name)
|
||||
.then(function() {
|
||||
uploader.submitFiles(stagedFiles); //note: must pass the file as part of an array.
|
||||
})
|
||||
.catch(function(error) {
|
||||
showError('input-error-claim-name', error);
|
||||
})
|
||||
};
|
||||
|
||||
/* socketio-file-upload listeners */
|
||||
uploader.addEventListener('start', function(event){
|
||||
var name = document.getElementById('publish-name').value;
|
||||
var license = document.getElementById('publish-license').value;
|
||||
var nsfw = document.getElementById('publish-nsfw').checked;
|
||||
event.file.meta.name = name;
|
||||
event.file.meta.license = license;
|
||||
event.file.meta.nsfw = nsfw;
|
||||
event.file.meta.type = stagedFiles[0].type;
|
||||
// re-set the html in the publish area
|
||||
document.getElementById('publish-active-area').innerHTML = '<div id="publish-status"></div><div id="progress-bar"></div>';
|
||||
// start a progress animation
|
||||
createProgressBar(document.getElementById('progress-bar'), 12);
|
||||
// google analytics
|
||||
ga('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: 'publish',
|
||||
eventAction: name
|
||||
});
|
||||
});
|
||||
uploader.addEventListener('progress', function(event){
|
||||
var percent = event.bytesLoaded / event.file.size * 100;
|
||||
updatePublishStatus('File is ' + percent.toFixed(2) + '% loaded to the server');
|
||||
});
|
||||
|
||||
/* socket.io message listeners */
|
||||
socket.on('publish-status', function(msg){
|
||||
updatePublishStatus(msg);
|
||||
});
|
||||
socket.on('publish-failure', function(msg){
|
||||
document.getElementById('publish-active-area').innerHTML = '<p> --(✖╭╮✖)→ </p><p>' + JSON.stringify(msg) + '</p><strong>For help, post the above error text in the #speech channel on the <a href="https://lbry.slack.com/" target="_blank">lbry slack</a></strong>';
|
||||
});
|
||||
|
||||
socket.on('publish-complete', function(msg){
|
||||
var publishResults;
|
||||
var showUrl = '/show/' + msg.name + '/' + msg.result.claim_id;
|
||||
// build new publish area
|
||||
publishResults = '<p>Your publish is complete! You are being redirected to it now.</p>';
|
||||
publishResults += '<p><a target="_blank" href="' + showUrl + '">If you do not get redirected, click here.</a></p>';
|
||||
// update publish area
|
||||
document.getElementById('publish-active-area').innerHTML = publishResults;
|
||||
window.location.href = showUrl;
|
||||
});
|
|
@ -2,7 +2,7 @@
|
|||
function updatePublishStatus(msg){
|
||||
document.getElementById('publish-status').innerHTML = msg;
|
||||
}
|
||||
|
||||
// validation function which checks the proposed file's type, size, and name
|
||||
function validateFile(file) {
|
||||
if (!file) {
|
||||
throw new Error('no file provided');
|
||||
|
@ -22,28 +22,28 @@ function validateFile(file) {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('The ' + file.Type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.')
|
||||
throw new Error(file.type + ' is not supported a supported file type. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.')
|
||||
}
|
||||
// validate the file name (note: different from the lbry claim name)
|
||||
var invalidCharacter = /[^\w.-\s()]/g.exec(file.name);
|
||||
if (invalidCharacter) {
|
||||
throw new Error('Special characters, such as "' + invalidCharacter + '", are not allowed in the file name.');
|
||||
};
|
||||
}
|
||||
|
||||
function validateSubmission(stagedFiles, name){
|
||||
// make sure only 1 file was selected
|
||||
if (!stagedFiles) {
|
||||
throw new FileError("Please select a file");
|
||||
} else if (stagedFiles.length > 1) {
|
||||
throw new FileError("Only one file is allowed at a time");
|
||||
}
|
||||
// validate 'name' field
|
||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||
if (invalidCharacters) {
|
||||
throw new NameError(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, and "-" only.');
|
||||
} else if (name.length < 1) {
|
||||
throw new NameError("You must enter a name for your claim");
|
||||
}
|
||||
}
|
||||
|
||||
// validation function that checks to make sure the claim name is not already claimed
|
||||
function validateClaimName (name) {
|
||||
var deferred = new Promise(function(resolve, reject) {
|
||||
// validate the characters in the 'name' field
|
||||
if (name.length < 1) {
|
||||
reject(new NameError("You must enter a name for your claim"));
|
||||
return;
|
||||
}
|
||||
var invalidCharacters = /[^A-Za-z0-9,-]/g.exec(name);
|
||||
if (invalidCharacters) {
|
||||
reject(new NameError('"' + invalidCharacters + '" is not allowed. Use only the following characters: A-Z, a-z, 0-9, and "-"'));
|
||||
return;
|
||||
}
|
||||
// make sure the claim name is still available
|
||||
var xhttp;
|
||||
xhttp = new XMLHttpRequest();
|
||||
xhttp.open('GET', '/api/isClaimAvailable/' + name, true);
|
||||
|
@ -54,7 +54,7 @@ function validateClaimName (name) {
|
|||
if (this.response == true) {
|
||||
resolve();
|
||||
} else {
|
||||
reject("That name has already been claimed by spee.ch. Please choose a different name.");
|
||||
reject( new NameError("That name has already been claimed by spee.ch. Please choose a different name."));
|
||||
}
|
||||
} else {
|
||||
reject("request to check claim name failed with status:" + this.status);
|
||||
|
@ -65,41 +65,87 @@ function validateClaimName (name) {
|
|||
});
|
||||
return deferred;
|
||||
}
|
||||
// validation function which checks all aspects of the publish submission
|
||||
function validateSubmission(stagedFiles, name){
|
||||
var deferred = new Promise(function (resolve, reject) {
|
||||
// make sure only 1 file was selected
|
||||
if (!stagedFiles) {
|
||||
reject(new FileError("Please select a file"));
|
||||
} else if (stagedFiles.length > 1) {
|
||||
reject(new FileError("Only one file is allowed at a time"));
|
||||
}
|
||||
// validate the file's name, type, and size
|
||||
try {
|
||||
validateFile(stagedFiles[0]);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
// make sure the claim name has not already been used
|
||||
validateClaimName(name)
|
||||
.then(function() {
|
||||
resolve();
|
||||
})
|
||||
.catch(function(error) {
|
||||
reject(error);
|
||||
})
|
||||
});
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/* regular publish helper functions */
|
||||
/* publish helper functions */
|
||||
|
||||
// When a file is selected for publish, validate that file and
|
||||
// stage it so it will be ready when the publish button is clicked.
|
||||
function previewAndStageFile(selectedFile){
|
||||
var previewHolder = document.getElementById('asset-preview-holder');
|
||||
var dropzone = document.getElementById('drop-zone');
|
||||
var previewReader = new FileReader();
|
||||
var nameInput = document.getElementById('publish-name');
|
||||
// validate the file
|
||||
// validate the file's name, type, and size
|
||||
try {
|
||||
validateFile(selectedFile);
|
||||
} catch (error) {
|
||||
showError('input-error-file-selection', error.message);
|
||||
return;
|
||||
}
|
||||
// set the preview
|
||||
if (selectedFile.type === 'video/mp4') {
|
||||
|
||||
} else {
|
||||
// set the image preview, if a preview was provided
|
||||
if (selectedFile.type !== 'video/mp4') {
|
||||
previewReader.readAsDataURL(selectedFile);
|
||||
previewReader.onloadend = function () {
|
||||
dropzone.style.display = 'none';
|
||||
previewHolder.style.display = 'block';
|
||||
previewHolder.innerHTML = '<img width="100%" src="' + previewReader.result + '" alt="image preview"/>';
|
||||
|
||||
previewHolder.innerHTML = '<img width="100%" src="' + previewReader.result + '" alt="image preview"/>';
|
||||
};
|
||||
}
|
||||
// set the name input value to the image name if none is set yet
|
||||
if (nameInput.value === "") {
|
||||
nameInput.value = selectedFile.name.substring(0, selectedFile.name.indexOf('.'));
|
||||
var filename = selectedFile.name.substring(0, selectedFile.name.indexOf('.'))
|
||||
nameInput.value = filename.replace(/\s+/g, '-');;
|
||||
}
|
||||
// store the selected file for upload
|
||||
stagedFiles = [selectedFile];
|
||||
}
|
||||
|
||||
// Validate the publish submission and then trigger publishing.
|
||||
function publishSelectedImage(event) {
|
||||
event.preventDefault();
|
||||
var name = document.getElementById('publish-name').value;
|
||||
validateSubmission(stagedFiles, name)
|
||||
.then(function() {
|
||||
uploader.submitFiles(stagedFiles);
|
||||
})
|
||||
.catch(function(error) {
|
||||
if (error.name === 'FileError'){
|
||||
showError('input-error-file-selection', error.message);
|
||||
} else if (error.name === 'NameError') {
|
||||
showError('input-error-claim-name', error.message);
|
||||
} else {
|
||||
showError('input-error-publish-submit', error.message);
|
||||
}
|
||||
return;
|
||||
})
|
||||
};
|
||||
|
||||
/* drop zone functions */
|
||||
|
||||
function drop_handler(ev) {
|
||||
|
@ -127,52 +173,4 @@ function dragend_handler(ev) {
|
|||
} else {
|
||||
ev.dataTransfer.clearData();
|
||||
}
|
||||
}
|
||||
|
||||
/* meme publish functions */
|
||||
|
||||
function startPublish() {
|
||||
//download the image
|
||||
var dataUrl = canvas.toDataURL('image/jpeg'); // canvas defined in memeDraw.js
|
||||
var blob = dataURItoBlob(dataUrl)
|
||||
var fileName = nameInput.value + ".jpeg"; //note: need to dynamically grab type
|
||||
var file = new File([blob], fileName, {type: 'image/jpeg', lastModified: Date.now()});
|
||||
stageAndPublish(file);
|
||||
};
|
||||
|
||||
function stageAndPublish(file) {
|
||||
var name = nameInput.value;
|
||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||
// validate 'name'
|
||||
if (invalidCharacters) {
|
||||
showError('input-error-claim-name', invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.');
|
||||
return;
|
||||
} else if (name.length < 1) {
|
||||
showError('input-error-claim-name', 'You must enter a name for your claim');
|
||||
return;
|
||||
}
|
||||
// stage files
|
||||
stagedFiles = [file]; // stores the selected file for
|
||||
// make sure a file was selected
|
||||
if (stagedFiles) {
|
||||
// make sure only 1 file was selected
|
||||
if (stagedFiles.length < 1) {
|
||||
showError('input-error-file-selection', 'A file is needed');
|
||||
return;
|
||||
}
|
||||
// make sure the content type is acceptable
|
||||
switch (stagedFiles[0].type) {
|
||||
case "image/png":
|
||||
case "image/jpeg":
|
||||
case "image/gif":
|
||||
case "video/mp4":
|
||||
uploader.submitFiles(stagedFiles);
|
||||
break;
|
||||
default:
|
||||
showError('input-error-publish-submit', 'Only .png, .jpeg, .gif, and .mp4 files are currently supported');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
showError('input-error-file-selection', 'Please select a file');
|
||||
}
|
||||
}
|
|
@ -10,7 +10,58 @@
|
|||
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script src="/siofu/client.js"></script>
|
||||
|
||||
<script src="/assets/js/generalFunctions.js"></script>
|
||||
<script src="/assets/js/publishFunctions.js"></script>
|
||||
<script src="/assets/js/index.js"></script>
|
||||
<script typ="text/javascript">
|
||||
// define variables
|
||||
var socket = io();
|
||||
var uploader = new SocketIOFileUpload(socket);
|
||||
var stagedFiles = null;
|
||||
/* socketio-file-upload listeners */
|
||||
uploader.addEventListener('start', function(event){
|
||||
var name = document.getElementById('publish-name').value;
|
||||
var license = document.getElementById('publish-license').value;
|
||||
var nsfw = document.getElementById('publish-nsfw').checked;
|
||||
event.file.meta.name = name;
|
||||
event.file.meta.license = license;
|
||||
event.file.meta.nsfw = nsfw;
|
||||
event.file.meta.type = stagedFiles[0].type;
|
||||
// re-set the html in the publish area
|
||||
document.getElementById('publish-active-area').innerHTML = '<div id="publish-status"></div><div id="progress-bar"></div>';
|
||||
// start a progress animation
|
||||
createProgressBar(document.getElementById('progress-bar'), 12);
|
||||
// google analytics
|
||||
ga('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: 'publish',
|
||||
eventAction: name
|
||||
});
|
||||
});
|
||||
uploader.addEventListener('progress', function(event){
|
||||
var percent = event.bytesLoaded / event.file.size * 100;
|
||||
updatePublishStatus('File is ' + percent.toFixed(2) + '% loaded to the server');
|
||||
});
|
||||
/* socket.io message listeners */
|
||||
socket.on('publish-status', function(msg){
|
||||
updatePublishStatus(msg);
|
||||
});
|
||||
socket.on('publish-failure', function(msg){
|
||||
document.getElementById('publish-active-area').innerHTML = '<p> --(✖╭╮✖)→ </p><p>' + JSON.stringify(msg) + '</p><strong>For help, post the above error text in the #speech channel on the <a href="https://lbry.slack.com/" target="_blank">lbry slack</a></strong>';
|
||||
});
|
||||
socket.on('publish-complete', function(msg){
|
||||
var publishResults;
|
||||
var showUrl = '/show/' + msg.name + '/' + msg.result.claim_id;
|
||||
// build new publish area
|
||||
publishResults = '<p>Your publish is complete! You are being redirected to it now.</p>';
|
||||
publishResults += '<p><a target="_blank" href="' + showUrl + '">If you do not get redirected, click here.</a></p>';
|
||||
// update publish area
|
||||
document.getElementById('publish-active-area').innerHTML = publishResults;
|
||||
window.location.href = showUrl;
|
||||
});
|
||||
|
||||
//event listener to filter claim name inputs
|
||||
document.getElementById('publish-name').addEventListener('input', function() {
|
||||
var name = this.value;
|
||||
this.value = name.replace(/\s+/g, '-');
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
<script>
|
||||
var elem = document.querySelector('.grid');
|
||||
var trendingImages = document.querySelectorAll('.trending-image');
|
||||
console.log(trendingImages)
|
||||
var trendingVideos = document.querySelectorAll('.trending-video');
|
||||
var msnry = new Masonry( elem, {
|
||||
itemSelector: '.grid-item'
|
||||
|
@ -34,14 +33,12 @@
|
|||
// after images are loaded, reset layout
|
||||
for (var i = 0; i < trendingVideos.length; i++) {
|
||||
trendingImages[i].addEventListener('load', function(){
|
||||
console.log('image loaded');
|
||||
msnry.layout();
|
||||
})
|
||||
}
|
||||
// after videos are loaded, reset layout
|
||||
for (var i = 0; i < trendingVideos.length; i++) {
|
||||
trendingVideos[i].addEventListener('loadeddata', function(){
|
||||
console.log('video loaded');
|
||||
msnry.layout();
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue