fixed bug letting re-publish to existing channel

This commit is contained in:
bill bittner 2017-10-04 14:03:19 -07:00
parent 282faec074
commit 580c63a1fb
7 changed files with 157 additions and 54 deletions

View file

@ -11,7 +11,7 @@ module.exports = new PassportLocalStrategy(
passReqToCallback: true, // we want to be able to read the post body message parameters in the callback passReqToCallback: true, // we want to be able to read the post body message parameters in the callback
}, },
(req, username, password, done) => { (req, username, password, done) => {
logger.debug(`new channel signup request: ${username} ${password}`); logger.debug(`new channel signup request. user: ${username} pass: ${password} .`);
let user; let user;
// server-side validaton of inputs (username, password) // server-side validaton of inputs (username, password)

View file

@ -24,10 +24,56 @@ p {
padding:0px; padding:0px;
} }
.url-text--primary {
color: black;
}
.url-text--secondary {
color: lightgrey;
}
.pull-quote { .pull-quote {
font-size: 3rem; font-size: 3rem;
} }
/* TOOL TIPS */
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}
/* Tooltip text */
.tooltip > .tooltip-text {
visibility: hidden;
width: 15em;
background-color: dodgerblue;
color: #fff;
text-align: center;
padding: 0.5em;
/* Position the tooltip text */
position: absolute;
z-index: 1;
bottom: 110%;
left: 50%;
margin-left: -8em; /* Use half of the width (120/2 = 60), to center the tooltip */
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover > .tooltip-text {
visibility: visible;
}
.tooltip > .tooltip-text::after {
content: " ";
position: absolute;
top: 100%; /* At the bottom of the tooltip */
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: dodgerblue transparent transparent transparent;
}
/* LINKS */ /* LINKS */
a, a:visited { a, a:visited {

View file

@ -50,14 +50,28 @@ function previewAndStageFile(selectedFile){
// Validate the publish submission and then trigger publishing. // Validate the publish submission and then trigger publishing.
function publishStagedFile(event) { function publishStagedFile(event) {
// prevent default so this script can handle submission
event.preventDefault();
// declare variables
const claimName = document.getElementById('claim-name-input').value; const claimName = document.getElementById('claim-name-input').value;
const channelName = document.getElementById('channel-name-select').value; let channelName = document.getElementById('channel-name-select').value;
const fileSelectionError = document.getElementById('input-error-file-selection'); const fileSelectionError = document.getElementById('input-error-file-selection');
const claimNameError = document.getElementById('input-error-claim-name'); const claimNameError = document.getElementById('input-error-claim-name');
const channelSelectError = document.getElementById('input-error-channel-select'); const channelSelectError = document.getElementById('input-error-channel-select');
const publishSubmitError = document.getElementById('input-error-publish-submit'); const publishSubmitError = document.getElementById('input-error-publish-submit');
// prevent default so this script can handle submission let anonymousOrInChannel;
event.preventDefault(); // replace channelName with 'anonymous' if needed
const radios = document.getElementsByName('anonymous-or-channel');
for (let i = 0; i < radios.length; i++) {
if (radios[i].checked) {
// do whatever you want with the checked radio
anonymousOrInChannel = radios[i].value;
// only one radio can be logically checked, don't check the rest
break;
}
}
if (anonymousOrInChannel === 'anonymous') {channelName = 'anonymous'};
console.log('channel name:', channelName);
// validate, submit, and handle response // validate, submit, and handle response
validateFilePublishSubmission(stagedFiles, claimName, channelName) validateFilePublishSubmission(stagedFiles, claimName, channelName)
.then(() => { .then(() => {

View file

@ -131,7 +131,7 @@ function checkAvailability(name, successDisplayElement, errorDisplayElement, val
function checkClaimName(name){ function checkClaimName(name){
const successDisplayElement = document.getElementById('input-success-claim-name'); const successDisplayElement = document.getElementById('input-success-claim-name');
const errorDisplayElement = document.getElementById('input-error-claim-name'); const errorDisplayElement = document.getElementById('input-error-claim-name');
checkAvailability(name, successDisplayElement, errorDisplayElement, validateClaimName, isNameAvailable, 'Sorry, that url ending has been taken by another user', '/api/isClaimAvailable/'); checkAvailability(name, successDisplayElement, errorDisplayElement, validateClaimName, isNameAvailable, 'Sorry, that url ending has been taken', '/api/isClaimAvailable/');
} }
function checkChannelName(name){ function checkChannelName(name){
@ -162,7 +162,7 @@ function validateFilePublishSubmission(stagedFiles, claimName, channelName){
} }
// 3. validate that a channel was chosen // 3. validate that a channel was chosen
if (channelName === 'new' || channelName === 'login') { if (channelName === 'new' || channelName === 'login') {
reject(new ChannelNameError("Please select a valid channel")); reject(new ChannelNameError("Please log in to a channel"));
return; return;
}; };
// 4. validate the claim name // 4. validate the claim name
@ -172,7 +172,7 @@ function validateFilePublishSubmission(stagedFiles, claimName, channelName){
reject(error); reject(error);
return; return;
} }
// if all validation passes, check availability of the name // if all validation passes, check availability of the name (note: do we need to re-validate channel name vs. credentials as well?)
return isNameAvailable(claimName, '/api/isClaimAvailable/') return isNameAvailable(claimName, '/api/isClaimAvailable/')
.then(result => { .then(result => {
if (result) { if (result) {
@ -188,7 +188,8 @@ function validateFilePublishSubmission(stagedFiles, claimName, channelName){
} }
// validation function which checks all aspects of a new channel submission // validation function which checks all aspects of a new channel submission
function validateNewChannelSubmission(channelName, password){ function validateNewChannelSubmission(userName, password){
const channelName = `@${userName}`;
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
// 1. validate name // 1. validate name
try { try {
@ -204,12 +205,17 @@ function validateNewChannelSubmission(channelName, password){
} }
// 3. if all validation passes, check availability of the name // 3. if all validation passes, check availability of the name
isNameAvailable(channelName, '/api/isChannelAvailable/') // validate the availability isNameAvailable(channelName, '/api/isChannelAvailable/') // validate the availability
.then(() => { .then(result => {
console.log('channel is available'); if (result) {
resolve(); console.log('channel is available');
resolve();
} else {
console.log('channel is not avaliable');
reject(new ChannelNameError('that channel name has already been taken'));
}
}) })
.catch( error => { .catch( error => {
console.log('error: channel is not avaliable'); console.log('error evaluating channel name availability', error);
reject(error); reject(error);
}); });
}); });

View file

@ -39,7 +39,7 @@
<script type="text/javascript"> <script type="text/javascript">
function publishNewChannel (event) { function publishNewChannel (event) {
const channelName = document.getElementById('new-channel-name').value; const userName = document.getElementById('new-channel-name').value;
const password = document.getElementById('new-channel-password').value; const password = document.getElementById('new-channel-password').value;
const channelNameErrorDisplayElement = document.getElementById('input-error-channel-name'); const channelNameErrorDisplayElement = document.getElementById('input-error-channel-name');
const passwordErrorDisplayElement = document.getElementById('input-error-channel-password'); const passwordErrorDisplayElement = document.getElementById('input-error-channel-password');
@ -50,13 +50,13 @@
// prevent default so this script can handle submission // prevent default so this script can handle submission
event.preventDefault(); event.preventDefault();
// validate submission // validate submission
validateNewChannelSubmission(channelName, password) validateNewChannelSubmission(userName, password)
.then(() => { .then(() => {
console.log('in progress'); console.log('in progress');
chanelCreateForm.hidden = true; chanelCreateForm.hidden = true;
inProgress.hidden = false; inProgress.hidden = false;
createProgressBar(document.getElementById('create-channel-progress-bar'), 12); createProgressBar(document.getElementById('create-channel-progress-bar'), 12);
return sendAuthRequest(channelName, password, '/signup') // post the request return sendAuthRequest(userName, password, '/signup') // post the request
}) })
.then(() => { .then(() => {
console.log('success'); console.log('success');

View file

@ -1,61 +1,95 @@
<!-- select whether to publish anonymously or in a channel -->
<div class="row"> <div class="row">
<div class="column column--3 column--sml-10"> <div class="column column--10">
<label class="label" for="channel-name-select">Channel:</label> <form>
</div><div class="column column--7 column--sml-10"> <label class="label" for="anonymous-select">Anonymous:</label>
<div id="input-error-channel-select" class="info-message info-message--failure"></div> <input type="radio" name="anonymous-or-channel" id="anonymous-select" class="" value="anonymous" {{#unless user}}checked {{/unless}} onchange="toggleChannel(event.target.value)"/>
<select type="text" id="channel-name-select" class="select select--primary select--arrow" value="channel" onchange="toggleChannel(event)"> <label class="label" for="in-a-channel-select">In a channel:</label>
{{#if user}} <input type="radio" name="anonymous-or-channel" id="in-a-channel-select" class="" value="in a channel" {{#if user}}checked {{/if}} onchange="toggleChannel(event.target.value)"/>
<option value="{{user.channelName}}" >@{{user.userName}}</option> </form>
{{/if}}
<option value="none" >None</option>
<option value="login">Login</option>
<option value="new" >New</option>
</select>
</div> </div>
</div> </div>
<div id="channel-login-details" class="row row--short" hidden="true"> <div id="channel-select-options" {{#unless user}}hidden="true"{{/unless}}>
{{> channelLoginForm}} <!-- select whether to create new or log in to existing channel -->
</div> <div class="row">
<div class="column column--3 column--sml-10">
<div id="channel-create-details" class="row row--short" hidden="true"> <label class="label" for="channel-name-select">Channel:</label>
{{> channelCreationForm}} </div><div class="column column--7 column--sml-10">
<div id="input-error-channel-select" class="info-message info-message--failure"></div>
<select type="text" id="channel-name-select" class="select select--primary select--arrow" onchange="toggleChannelSelect(event.target.selectedOptions[0].value)">
{{#if user}}
<option value="{{user.channelName}}" >{{user.channelName}}</option>
{{/if}}
<option value="login">Existing</option>
<option value="new" >New</option>
</select>
</div>
</div>
<!-- log into an existing channel -->
<div id="channel-login-details" class="row row--short" {{#if user}}hidden="true"{{/if}}>
{{> channelLoginForm}}
</div>
<!-- create a channel -->
<div id="channel-create-details" class="row row--short" hidden="true">
{{> channelCreationForm}}
</div>
</div> </div>
<script src="/assets/js/authFunctions.js"></script> <script src="/assets/js/authFunctions.js"></script>
<script type="text/javascript"> <script type="text/javascript">
function toggleChannel (event) { function updateUrl (selectedOption) {
const urlChannel = document.getElementById('url-channel');
if (selectedOption === 'new' || selectedOption === 'login'){
// update URL
urlChannel.innerText = '@channelName';
//toolTipText.innerText = 'will be replaced by your channel and id';
urlChannel.setAttribute('class', 'url-text url-text--secondary')
} else if (selectedOption === 'anonymous'){
urlChannel.innerText = 'xyz';
//toolTipText.innerText = 'will be replaced by a random id';
urlChannel.setAttribute('class', 'url-text url-text--secondary')
} else {
urlChannel.innerText = `{{user.channelName}}:{{user.shortChannelId}}`;
//toolTipText.innerText = '';
urlChannel.setAttribute('class', 'url-text url-text--primary')
}
}
// show or hide the channel selection tools
function toggleChannel (selectedOption) {
const channelSelectOptions = document.getElementById('channel-select-options');
console.log('toggleChannel event triggered', selectedOption);
// show/hide the login and new channel forms
if (selectedOption === 'anonymous') {
channelSelectOptions.hidden = true;
channelSelectOptions.hidden = true;
} else if (selectedOption === 'in a channel') {
channelSelectOptions.hidden = false;
} else {
console.log('selected option was not recognized');
}
// update url
updateUrl(selectedOption);
}
// show or hide the channel create/login tool
function toggleChannelSelect (selectedOption) {
const createChannelTool = document.getElementById('channel-create-details'); const createChannelTool = document.getElementById('channel-create-details');
const loginToChannelTool = document.getElementById('channel-login-details'); const loginToChannelTool = document.getElementById('channel-login-details');
const selectedOption = event.target.selectedOptions[0].value; console.log('toggleChannelSelect event triggered', selectedOption);
const urlChannel = document.getElementById('url-channel'); // show/hide the login and new channel forms
console.log('toggle event triggered');
if (selectedOption === 'new') { if (selectedOption === 'new') {
// show/hide the login and new channel forms
createChannelTool.hidden = false; createChannelTool.hidden = false;
loginToChannelTool.hidden = true; loginToChannelTool.hidden = true;
// update URL
urlChannel.innerText = '';
} else if (selectedOption === 'login') { } else if (selectedOption === 'login') {
// show/hide the login and new channel forms
loginToChannelTool.hidden = false; loginToChannelTool.hidden = false;
createChannelTool.hidden = true; createChannelTool.hidden = true;
// update URL
urlChannel.innerText = '';
} else { } else {
// hide the login and new channel forms // hide the login and new channel forms
loginToChannelTool.hidden = true; loginToChannelTool.hidden = true;
createChannelTool.hidden = true; createChannelTool.hidden = true;
hideError(document.getElementById('input-error-channel-select')); hideError(document.getElementById('input-error-channel-select'));
// update URL
if (selectedOption === 'none'){
console.log('selected option: none');
urlChannel.innerText = '';
} else {
console.log('selected option:', selectedOption);
// retrieve short url from db
urlChannel.innerText = `{{user.channelName}}:{{user.shortChannelId}}/`;
}
} }
// update url
updateUrl(selectedOption);
} }
</script> </script>

View file

@ -5,8 +5,11 @@
</div><div class="column column--6 column--sml-10"> </div><div class="column column--6 column--sml-10">
<div id="input-error-claim-name" class="info-message info-message--failure" hidden="true"></div> <div id="input-error-claim-name" class="info-message info-message--failure" hidden="true"></div>
<div class="input-text--primary"> <div class="input-text--primary">
<span class="url-text">Spee.ch/</span><span id="url-channel" class="url-text">{{#if user}}{{user.channelName}}:{{user.shortChannelId}}/{{/if}}</span><input type="text" id="claim-name-input" class="input-text" placeholder="your-url-here" oninput="checkClaimName(event.target.value)"> {{#if user}}
<span id="input-success-claim-name" class="info-message info-message--success"></span> <span class="url-text">Spee.ch/</span><span id="url-channel" class="url-text url-text--primary">{{user.channelName}}:{{user.shortChannelId}}</span>/<input type="text" id="claim-name-input" class="input-text" placeholder="your-url-here" oninput="checkClaimName(event.target.value)"><span id="input-success-claim-name" class="info-message info-message--success"></span>
{{else}}
<span class="url-text">Spee.ch/</span><span id="url-channel" class="url-text url-text--secondary">xyz</span>/<input type="text" id="claim-name-input" class="input-text" placeholder="your-url-here" oninput="checkClaimName(event.target.value)"><span id="input-success-claim-name" class="info-message info-message--success"></span>
{{/if}}
</div> </div>
</div> </div>