finished basic loop for channel creation
This commit is contained in:
parent
86a2c6fe03
commit
0dd8e19a26
15 changed files with 158 additions and 32 deletions
|
@ -6,7 +6,7 @@ module.exports = {
|
|||
'UserId',
|
||||
{
|
||||
type : Sequelize.STRING,
|
||||
allowNull: false,
|
||||
allowNull: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
20
migrations/remove-Email-from-User.js
Normal file
20
migrations/remove-Email-from-User.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
module.exports = {
|
||||
up: (queryInterface, Sequelize) => {
|
||||
// logic for transforming into the new state
|
||||
return queryInterface.removeColumn(
|
||||
'User',
|
||||
'Email'
|
||||
);
|
||||
},
|
||||
down: (queryInterface, Sequelize) => {
|
||||
// logic for reverting the changes
|
||||
return queryInterface.addColumn(
|
||||
'User',
|
||||
'Email',
|
||||
{
|
||||
type : Sequelize.STRING,
|
||||
allowNull: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
|
@ -14,10 +14,6 @@ module.exports = (sequelize, { STRING }) => {
|
|||
type : STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
email: {
|
||||
type : STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
address: {
|
||||
type : STRING,
|
||||
allowNull: false,
|
||||
|
|
|
@ -10,6 +10,7 @@ module.exports = new PassportLocalStrategy(
|
|||
passReqToCallback: true,
|
||||
},
|
||||
(req, username, password, done) => {
|
||||
username = `@${username}`;
|
||||
return db.User
|
||||
.findOne({where: {channelName: username}})
|
||||
.then(user => {
|
||||
|
|
|
@ -2,6 +2,7 @@ const db = require('../models');
|
|||
const PassportLocalStrategy = require('passport-local').Strategy;
|
||||
const lbryApi = require('../helpers/lbryApi.js');
|
||||
const logger = require('winston');
|
||||
const config = require('config');
|
||||
|
||||
module.exports = new PassportLocalStrategy(
|
||||
{
|
||||
|
@ -11,20 +12,34 @@ module.exports = new PassportLocalStrategy(
|
|||
passReqToCallback: true, // we want to be able to read the post body message parameters in the callback
|
||||
},
|
||||
(req, username, password, done) => {
|
||||
console.log('inside local-signup');
|
||||
logger.debug('new channel signup request');
|
||||
const address = config.get('WalletConfig.LbryClaimAddress');
|
||||
// validate raw inputs (username, password)
|
||||
username = '@' + username;
|
||||
// create the channel and retrieve the metadata
|
||||
lbryApi.createChannel(username)
|
||||
.then(channelInfo => {
|
||||
// define an object that contains all the user data
|
||||
return lbryApi.createChannel(username)
|
||||
.then(channelTx => {
|
||||
// create certificate record
|
||||
const certificateData = {
|
||||
address,
|
||||
claimId: channelTx.claim_id,
|
||||
name : username,
|
||||
};
|
||||
logger.debug('certificateData >', certificateData);
|
||||
return db.Certificate.create(certificateData);
|
||||
})
|
||||
.then(certificate => {
|
||||
logger.debug('certificate result >', certificate.dataValues);
|
||||
logger.debug('Certificate record was created successfully');
|
||||
// define an object that contains all the user data
|
||||
const userData = {
|
||||
channelName : username,
|
||||
channelClaimId: channelInfo.claim_id,
|
||||
channelClaimId: certificate.claimId,
|
||||
password : password,
|
||||
email : 'test email', // req.body.email.trim(),
|
||||
address,
|
||||
};
|
||||
return db.User.create(userData);
|
||||
})
|
||||
.then(user => {
|
||||
}).then(user => {
|
||||
logger.debug('User record was created successfully');
|
||||
return done(null, user); // user.datavalues?
|
||||
})
|
||||
|
|
26
public/assets/js/channelFunctions.js
Normal file
26
public/assets/js/channelFunctions.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
function sendSignupRequest (channelName, password) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
// make sure the claim name is still available
|
||||
let xhttp;
|
||||
const params = `username=${channelName}&password=${password}`;
|
||||
console.log(params);
|
||||
xhttp = new XMLHttpRequest();
|
||||
xhttp.open('POST', '/api/signup', true);
|
||||
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhttp.responseType = 'json';
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 ) {
|
||||
if ( this.status == 200) {
|
||||
if (this.response == true) {
|
||||
resolve();
|
||||
} else {
|
||||
reject( new NameError("Your request could not be completed"));
|
||||
}
|
||||
} else {
|
||||
reject("createChannel request failed with status:" + this.status);
|
||||
};
|
||||
}
|
||||
};
|
||||
xhttp.send(params);
|
||||
});
|
||||
}
|
|
@ -40,6 +40,26 @@ function validateClaimName (name) {
|
|||
}
|
||||
}
|
||||
|
||||
function validateChannelName (name) {
|
||||
name = name.substring(name.indexOf('@') + 1);
|
||||
console.log(name);
|
||||
// ensure a name was entered
|
||||
if (name.length < 1) {
|
||||
throw new ChannelError("You must enter a name for your channel");
|
||||
}
|
||||
// validate the characters in the 'name' field
|
||||
const invalidCharacters = /[^A-Za-z0-9,-,@]/g.exec(name);
|
||||
if (invalidCharacters) {
|
||||
throw new ChannelError('"' + invalidCharacters + '" characters are not allowed in the channel name.');
|
||||
}
|
||||
}
|
||||
|
||||
function validatePassword (password) {
|
||||
if (password.length < 1) {
|
||||
throw new ChannelError("You must enter a password for you channel");
|
||||
}
|
||||
}
|
||||
|
||||
function cleanseClaimName(name) {
|
||||
name = name.replace(/\s+/g, '-'); // replace spaces with dashes
|
||||
name = name.replace(/[^A-Za-z0-9-]/g, ''); // remove all characters that are not A-Z, a-z, 0-9, or '-'
|
||||
|
@ -92,10 +112,10 @@ function hideSuccess (successElement) {
|
|||
successElement.innerHTML = "";
|
||||
}
|
||||
|
||||
function checkAvailability(name, successDisplayElement, errorDisplayElement, isNameAvailable, apiUrl) {
|
||||
function checkAvailability(name, successDisplayElement, errorDisplayElement, validateName, isNameAvailable, apiUrl) {
|
||||
try {
|
||||
// check to make sure the characters are valid
|
||||
validateClaimName(name);
|
||||
validateName(name);
|
||||
// check to make sure it is available
|
||||
isNameAvailable(name, apiUrl)
|
||||
.then(function() {
|
||||
|
@ -115,13 +135,14 @@ function checkAvailability(name, successDisplayElement, errorDisplayElement, isN
|
|||
function checkClaimName(name){
|
||||
const successDisplayElement = document.getElementById('input-success-claim-name');
|
||||
const errorDisplayElement = document.getElementById('input-error-claim-name');
|
||||
checkAvailability(name, successDisplayElement, errorDisplayElement, isNameAvailable, '/api/isClaimAvailable/');
|
||||
checkAvailability(name, successDisplayElement, errorDisplayElement, validateClaimName, isNameAvailable, '/api/isClaimAvailable/');
|
||||
}
|
||||
|
||||
function checkChannelName(name){
|
||||
const successDisplayElement = document.getElementById('input-success-channel-name');
|
||||
const errorDisplayElement = document.getElementById('input-error-channel-name');
|
||||
checkAvailability(name, successDisplayElement, errorDisplayElement, isNameAvailable, '/api/isChannelAvailable/');
|
||||
name = `@${name}`;
|
||||
checkAvailability(name, successDisplayElement, errorDisplayElement, validateChannelName, isNameAvailable, '/api/isChannelAvailable/');
|
||||
}
|
||||
|
||||
// validation function which checks all aspects of the publish submission
|
||||
|
@ -158,4 +179,4 @@ function validateSubmission(stagedFiles, claimName, channelName){
|
|||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -6,8 +6,18 @@ const { getClaimList, resolveUri } = require('../helpers/lbryApi.js');
|
|||
const { createPublishParams, validateFile, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js');
|
||||
const errorHandlers = require('../helpers/errorHandlers.js');
|
||||
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
|
||||
const passport = require('passport');
|
||||
|
||||
module.exports = (app, hostedContentPath) => {
|
||||
// route for auth
|
||||
app.post('/api/signup', passport.authenticate('local-signup'), (req, res) => {
|
||||
logger.debug('successful signup');
|
||||
res.status(200).json(true);
|
||||
});
|
||||
app.post('/api/login', passport.authenticate('local-login'), (req, res) => {
|
||||
logger.debug('successful login');
|
||||
res.status(200).json(true);
|
||||
});
|
||||
// route to run a claim_list request on the daemon
|
||||
app.get('/api/claim_list/:name', ({ headers, ip, originalUrl, params }, res) => {
|
||||
// google analytics
|
||||
|
|
|
@ -9,13 +9,13 @@ module.exports = (app) => {
|
|||
logger.debug('redirecting to user channel');
|
||||
// If this function gets called, signup was successful.
|
||||
// `req.user` contains the authenticated user.
|
||||
res.redirect('/@' + req.user.channelName);
|
||||
res.redirect(`/${req.user.channelName}`);
|
||||
});
|
||||
app.post('/login', passport.authenticate('local-login'), (req, res) => {
|
||||
logger.debug('redirecting to user channel');
|
||||
// If this function gets called, login was successful.
|
||||
// `req.user` contains the authenticated user.
|
||||
res.redirect('/@' + req.user.channelName);
|
||||
res.redirect(`/${req.user.channelName}`);
|
||||
});
|
||||
// route to log out
|
||||
app.get('/logout', (req, res) => {
|
||||
|
@ -26,7 +26,7 @@ module.exports = (app) => {
|
|||
// route to display login page
|
||||
app.get('/login', (req, res) => {
|
||||
if (req.user) {
|
||||
res.status(200).redirect(`/@${req.user.channelName}`);
|
||||
res.status(200).redirect(`/${req.user.channelName}`);
|
||||
} else {
|
||||
res.status(200).render('login');
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ app.use(bodyParser.urlencoded({ extended: true })); // 'body parser' for parsing
|
|||
app.use(siofu.router); // 'socketio-file-upload' router for uploading with socket.io
|
||||
app.use((req, res, next) => { // custom logging middleware to log all incoming http requests
|
||||
logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`);
|
||||
logger.debug(req.body);
|
||||
next();
|
||||
});
|
||||
|
||||
|
@ -75,6 +76,7 @@ app.use((req, res, next) => {
|
|||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// start the server
|
||||
db.sequelize
|
||||
.sync() // sync sequelize
|
||||
|
|
|
@ -64,5 +64,4 @@
|
|||
document.getElementById('publish-active-area').innerHTML = publishResults;
|
||||
window.location.href = showUrl;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="full">
|
||||
|
||||
<h2>Log In</h2>
|
||||
<p>Log in to an existing channel</p>
|
||||
<p>Log in to an existing channel:</p>
|
||||
<form id="login-form" action="/login" method="post">
|
||||
<div>
|
||||
<label>Username:</label>
|
||||
|
@ -19,21 +19,56 @@
|
|||
</form>
|
||||
|
||||
<h2>Create New</h2>
|
||||
<p>Create a brand new channel</p>
|
||||
<form action="/signup" method="post">
|
||||
<p>Create a brand new channel:</p>
|
||||
<span id="input-error-channel-name" class="info-message info-message--failure"></span><br/>
|
||||
<form id="signup-form" action="/signup" method="post">
|
||||
<div>
|
||||
<label>Channel name:</label>
|
||||
@ <input type="text" name="username" class="input-text input-text--primary"/>
|
||||
@ <input type="text" name="username" value="" id="new-channel-name" class="input-text input-text--primary" oninput="checkChannelName(event.target.value)"/>
|
||||
<span id="input-success-channel-name" class="info-message info-message--success"></span>
|
||||
</div>
|
||||
<div>
|
||||
<span id="input-error-password" class="info-message info-message--failure"></span><br/>
|
||||
<label>Password:</label>
|
||||
<input type="password" name="password" class="input-text input-text--primary"/>
|
||||
<input type="password" name="password" value="" id="new-channel-password" class="input-text input-text--primary"/>
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" value="Create"/>
|
||||
<input type="submit" value="Create" onclick="submitNewChannelRequest(event)"/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{{> footer}}
|
||||
</div>
|
||||
|
||||
<script src="/assets/js/generalFunctions.js"></script>
|
||||
<script src="/assets/js/validationFunctions.js"></script>
|
||||
<script src="/assets/js/channelFunctions.js"></script>
|
||||
<script type="text/javascript">
|
||||
function submitNewChannelRequest (event) {
|
||||
const channelName = document.getElementById('new-channel-name').value;
|
||||
const password = document.getElementById('new-channel-password').value;
|
||||
// prevent default so this script can handle submission
|
||||
event.preventDefault();
|
||||
// validate channel name
|
||||
|
||||
|
||||
// validate password
|
||||
try {
|
||||
validatePassword(password);
|
||||
} catch (error) {
|
||||
showError(document.getElementById('input-error-password'), error.message)
|
||||
return;
|
||||
}
|
||||
// post request
|
||||
sendSignupRequest(channelName, password)
|
||||
.then(() => {
|
||||
console.log('success');
|
||||
document.getElementById('signup-form').innerHTML = '<p>Your channel has been successfully created! Redirecting you now...</p>';
|
||||
window.location.href = '/channelName';
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<label for="channel-name-select">Channel:</label>
|
||||
<select type="text" id="channel-name-select" name="channel" value="channel" onclick="check(event)">
|
||||
{{#if user}}
|
||||
<option value="@{{user.channelName}}" >@{{user.channelName}}</option>
|
||||
<option value="{{user.channelName}}" >{{user.channelName}}</option>
|
||||
{{/if}}
|
||||
<option value="@speech" >Anonymous</option>
|
||||
<option value="new" >New</option>
|
||||
|
@ -15,7 +15,7 @@
|
|||
<span id="input-error-channel-name" class="info-message info-message--failure"></span>
|
||||
<p>
|
||||
<label for="channelName">Channel Name: </label>
|
||||
@<input type="text" id="channel-name-input" class="input-text input-text--primary" placeholder="exampleChannel" value=""; oninput="checkChannelName(event.target.value)">
|
||||
@<input type="text" id="channel-name-input" class="input-text input-text--primary" placeholder="exampleChannel" value="" oninput="checkChannelName(event.target.value)">
|
||||
<span id="input-success-channel-name" class="info-message info-message--success"></span>
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -25,4 +25,5 @@
|
|||
<td><input type="checkbox" id="publish-nsfw"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<a href="/about" class="top-bar-right">help</a>
|
||||
|
||||
{{#if user}}
|
||||
<a href="/@{{user.channelName}}" class="top-bar-right">@{{user.channelName}}</a>
|
||||
<a href="/{{user.channelName}}" class="top-bar-right">{{user.channelName}}</a>
|
||||
<a href="/logout" class="top-bar-right">logout</a>
|
||||
{{else}}
|
||||
<a href="/login" class="top-bar-right">login</a>
|
||||
|
|
Loading…
Add table
Reference in a new issue