fixed the anonymous discrepency
This commit is contained in:
parent
d92f499269
commit
e34e78c169
8 changed files with 97 additions and 96 deletions
20
README.md
20
README.md
|
@ -36,17 +36,17 @@ spee.ch is a single-serving site that reads and publishes images and videos to a
|
|||
|
||||
#### POST
|
||||
* /api/publish
|
||||
* example: `curl -X POST -F 'name=MyPictureName' -F 'nsfw=false' -F 'file=@/path/to/my/picture.jpeg' https://spee.ch/api/publish`
|
||||
* example: `curl -X POST -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/publish`
|
||||
* Parameters:
|
||||
* name (string)
|
||||
* nsfw (boolean)
|
||||
* file (.mp4, .jpeg, .jpg, .gif, or .png)
|
||||
* license (string, optional)
|
||||
* title (string, optional)
|
||||
* description (string, optional)
|
||||
* thumbnail (string, optional) (for .mp4 uploads only)
|
||||
* channelName(string, optional)
|
||||
* channelPassword (string, optional)
|
||||
* `name`
|
||||
* `file` (.mp4, .jpeg, .jpg, .gif, or .png)
|
||||
* `nsfw` (optional)
|
||||
* `license` (optional)
|
||||
* `title` (optional)
|
||||
* `description` (optional)
|
||||
* `thumbnail` url to thumbnail image, for .mp4 uploads only (optional)
|
||||
* `channelName`(optional)
|
||||
* `channelPassword` (optional,; required if `channelName` is provided)
|
||||
|
||||
## bugs
|
||||
If you find a bug or experience a problem, please report your issue here on github and find us in the lbry slack!
|
||||
|
|
|
@ -2,12 +2,14 @@ const db = require('../models');
|
|||
const logger = require('winston');
|
||||
|
||||
module.exports = {
|
||||
authenticateChannelCredentials (channelName, userPassword) {
|
||||
authenticateChannelCredentials (skipAuth, channelName, userPassword) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!channelName) {
|
||||
resolve(true);
|
||||
// skip authentication if not needed
|
||||
if (skipAuth) {
|
||||
resolve(skipAuth);
|
||||
return;
|
||||
}
|
||||
// authentication
|
||||
const userName = channelName.substring(1);
|
||||
logger.debug(`authenticateChannelCredentials > channelName: ${channelName} username: ${userName} pass: ${userPassword}`);
|
||||
db.User
|
||||
|
@ -18,17 +20,23 @@ module.exports = {
|
|||
resolve(false);
|
||||
return;
|
||||
}
|
||||
if (!user.validPassword(userPassword, user.password)) {
|
||||
logger.debug('incorrect password');
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
logger.debug('user found:', user.dataValues);
|
||||
resolve(true);
|
||||
return user.comparePassword(userPassword, (passwordErr, isMatch) => {
|
||||
if (passwordErr) {
|
||||
logger.error('comparePassword error:', passwordErr);
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
if (!isMatch) {
|
||||
logger.debug('incorrect password');
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
logger.debug('...password was a match...');
|
||||
resolve(true);
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error(error);
|
||||
reject();
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
@ -13,17 +13,16 @@ module.exports = {
|
|||
.then(tx => {
|
||||
logger.info(`Successfully published ${fileName}`, tx);
|
||||
publishResults = tx;
|
||||
return db.Channel.findOne({where: {channelName: publishParams.channel_name}}); // note: should this be db.User ??
|
||||
})
|
||||
.then(channel => {
|
||||
let certificateId;
|
||||
if (channel) {
|
||||
certificateId = channel.channelClaimId;
|
||||
logger.debug('successfully found channel in Channel table');
|
||||
if (publishParams.channel_name) {
|
||||
logger.debug(`this claim was published in channel: ${publishParams.channel_name}`);
|
||||
return db.Channel.findOne({where: {channelName: publishParams.channel_name}}).then(channel => { return channel.channelClaimId });
|
||||
} else {
|
||||
certificateId = null;
|
||||
logger.debug('channel for publish not found in Channel table');
|
||||
};
|
||||
logger.debug('this claim was published in channel: n/a');
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.then(certificateId => {
|
||||
logger.debug(`certificateId: ${certificateId}`);
|
||||
const fileRecord = {
|
||||
name : publishParams.name,
|
||||
claimId : publishResults.claim_id,
|
||||
|
|
|
@ -3,11 +3,12 @@ const { postToStats } = require('../controllers/statsController.js');
|
|||
|
||||
module.exports = {
|
||||
returnErrorMessageAndStatus: function (error) {
|
||||
let status;
|
||||
let message;
|
||||
let status, message;
|
||||
// check for daemon being turned off
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
status = 503;
|
||||
message = 'Connection refused. The daemon may not be running.';
|
||||
// check for errors from the deamon
|
||||
} else if (error.response) {
|
||||
status = error.response.status || 500;
|
||||
if (error.response.data) {
|
||||
|
@ -21,7 +22,13 @@ module.exports = {
|
|||
} else {
|
||||
message = error.response;
|
||||
}
|
||||
// check for spee.ch thrown errors
|
||||
} else if (error.message) {
|
||||
status = 400;
|
||||
message = error.message;
|
||||
// fallback for everything else
|
||||
} else {
|
||||
status = 400;
|
||||
message = error;
|
||||
}
|
||||
return [status, message];
|
||||
|
|
|
@ -18,11 +18,10 @@ module.exports = {
|
|||
throw new Error('no file with key of [file] found in request');
|
||||
}
|
||||
},
|
||||
validatePublishSubmission (file, claimName, nsfw) {
|
||||
validatePublishSubmission (file, claimName) {
|
||||
try {
|
||||
module.exports.validateFile(file);
|
||||
module.exports.validateClaimName(claimName);
|
||||
module.exports.validateNSFW(nsfw);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
@ -76,24 +75,6 @@ module.exports = {
|
|||
throw new Error('Only posts with a "Public Domain" or "Creative Commons" license are eligible for publishing through spee.ch');
|
||||
}
|
||||
},
|
||||
cleanseNSFW (nsfw) {
|
||||
switch (nsfw) {
|
||||
case true:
|
||||
case 'on':
|
||||
case 'true':
|
||||
case 1:
|
||||
case '1':
|
||||
return true;
|
||||
case false:
|
||||
case 'false':
|
||||
case 'off':
|
||||
case 0:
|
||||
case '0':
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
cleanseChannelName (channelName) {
|
||||
if (channelName) {
|
||||
if (channelName.indexOf('@') !== 0) {
|
||||
|
@ -102,12 +83,6 @@ module.exports = {
|
|||
}
|
||||
return channelName;
|
||||
},
|
||||
validateNSFW (nsfw) {
|
||||
if (nsfw === true || nsfw === false) {
|
||||
return;
|
||||
}
|
||||
throw new Error('NSFW must be set to either true or false');
|
||||
},
|
||||
createPublishParams (filePath, name, title, description, license, nsfw, thumbnail, channelName) {
|
||||
logger.debug(`Creating Publish Parameters`);
|
||||
// provide defaults for title
|
||||
|
|
|
@ -64,20 +64,12 @@ var publishFileFunctions = {
|
|||
}
|
||||
},
|
||||
returnNullOrChannel: function () {
|
||||
const channelInput = document.getElementById('channel-name-select');
|
||||
const radios = document.getElementsByName('anonymous-or-channel');
|
||||
let anonymousOrInChannel;
|
||||
// replace channelName with 'anonymous' if appropriate
|
||||
for (let i = 0; i < radios.length; i++) {
|
||||
if (radios[i].checked) {
|
||||
anonymousOrInChannel = radios[i].value; // do whatever you want with the checked radio
|
||||
break; // only one radio can be logically checked, don't check the rest
|
||||
}
|
||||
const channelRadio = document.getElementById('channel-radio');
|
||||
if (channelRadio.checked) {
|
||||
const channelInput = document.getElementById('channel-name-select');
|
||||
return channelInput.value.trim();
|
||||
}
|
||||
if (anonymousOrInChannel === 'anonymous') {
|
||||
return null;
|
||||
};
|
||||
return channelInput.value.trim();
|
||||
return null;
|
||||
},
|
||||
createMetadata: function() {
|
||||
const nameInput = document.getElementById('claim-name-input');
|
||||
|
@ -89,13 +81,13 @@ var publishFileFunctions = {
|
|||
|
||||
return {
|
||||
name: nameInput.value.trim(),
|
||||
channel: this.returnNullOrChannel(),
|
||||
channelName: this.returnNullOrChannel(),
|
||||
title: titleInput.value.trim(),
|
||||
description: descriptionInput.value.trim(),
|
||||
license: licenseInput.value.trim(),
|
||||
nsfw: nsfwInput.checked,
|
||||
type: stagedFiles[0].type,
|
||||
thumbnail: thumbnailInput.value.trim()
|
||||
thumbnail: thumbnailInput.value.trim(),
|
||||
}
|
||||
},
|
||||
appendDataToFormData: function (file, metadata) {
|
||||
|
|
|
@ -4,7 +4,7 @@ const multipartMiddleware = multipart();
|
|||
const db = require('../models');
|
||||
const { publish } = require('../controllers/publishController.js');
|
||||
const { getClaimList, resolveUri } = require('../helpers/lbryApi.js');
|
||||
const { createPublishParams, validateApiPublishRequest, validatePublishSubmission, cleanseNSFW, cleanseChannelName, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js');
|
||||
const { createPublishParams, validateApiPublishRequest, validatePublishSubmission, cleanseChannelName, checkClaimNameAvailability, checkChannelAvailability } = require('../helpers/publishHelpers.js');
|
||||
const errorHandlers = require('../helpers/errorHandlers.js');
|
||||
const { postToStats, sendGoogleAnalytics } = require('../controllers/statsController.js');
|
||||
const { authenticateChannelCredentials } = require('../auth/authentication.js');
|
||||
|
@ -71,7 +71,9 @@ module.exports = (app) => {
|
|||
});
|
||||
});
|
||||
// route to run a publish request on the daemon
|
||||
app.post('/api/publish', multipartMiddleware, ({ body, files, ip, originalUrl }, res) => {
|
||||
app.post('/api/publish', multipartMiddleware, ({ body, files, ip, originalUrl, user }, res) => {
|
||||
logger.debug('api/publish body:', body);
|
||||
let file, fileName, filePath, fileType, name, nsfw, license, title, description, thumbnail, anonymous, skipAuth, channelName, channelPassword;
|
||||
// validate that mandatory parts of the request are present
|
||||
try {
|
||||
validateApiPublishRequest(body, files);
|
||||
|
@ -81,12 +83,12 @@ module.exports = (app) => {
|
|||
return;
|
||||
}
|
||||
// validate file, name, license, and nsfw
|
||||
const file = files.file;
|
||||
const fileName = file.name;
|
||||
const filePath = file.path;
|
||||
const fileType = file.type;
|
||||
const name = body.name;
|
||||
const nsfw = cleanseNSFW(body.nsfw); // cleanse nsfw input
|
||||
file = files.file;
|
||||
fileName = file.name;
|
||||
filePath = file.path;
|
||||
fileType = file.type;
|
||||
name = body.name;
|
||||
nsfw = (body.nsfw === 'true');
|
||||
try {
|
||||
validatePublishSubmission(file, name, nsfw);
|
||||
} catch (error) {
|
||||
|
@ -94,18 +96,36 @@ module.exports = (app) => {
|
|||
res.status(400).json({success: false, message: error.message});
|
||||
return;
|
||||
}
|
||||
logger.debug(`name: ${name}, nsfw: ${nsfw}`);
|
||||
// optional inputs
|
||||
const license = body.license || null;
|
||||
const title = body.title || null;
|
||||
const description = body.description || null;
|
||||
const thumbnail = body.thumbnail || null;
|
||||
let channelName = body.channelName || null;
|
||||
license = body.license || null;
|
||||
title = body.title || null;
|
||||
description = body.description || null;
|
||||
thumbnail = body.thumbnail || null;
|
||||
anonymous = (body.channelName === 'null') || (body.channelName === undefined);
|
||||
if (user) {
|
||||
channelName = user.channelName || null;
|
||||
} else {
|
||||
channelName = body.channelName || null;
|
||||
}
|
||||
channelPassword = body.channelPassword || null;
|
||||
skipAuth = false;
|
||||
// case 1: publish from spee.ch, client logged in
|
||||
if (user) {
|
||||
skipAuth = true;
|
||||
if (anonymous) {
|
||||
channelName = null;
|
||||
}
|
||||
// case 2: publish from api or spee.ch, client not logged in
|
||||
} else {
|
||||
if (anonymous) {
|
||||
skipAuth = true;
|
||||
channelName = null;
|
||||
}
|
||||
}
|
||||
channelName = cleanseChannelName(channelName);
|
||||
const channelPassword = body.channelPassword || null;
|
||||
logger.debug(`license: ${license} title: "${title}" description: "${description}" channelName: "${channelName}" channelPassword: "${channelPassword}" nsfw: "${nsfw}"`);
|
||||
logger.debug(`name: ${name}, license: ${license} title: "${title}" description: "${description}" channelName: "${channelName}" channelPassword: "${channelPassword}" nsfw: "${nsfw}"`);
|
||||
// check channel authorization
|
||||
authenticateChannelCredentials(channelName, channelPassword)
|
||||
authenticateChannelCredentials(skipAuth, channelName, channelPassword)
|
||||
.then(result => {
|
||||
if (!result) {
|
||||
throw new Error('Authentication failed, you do not have access to that channel');
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
<div class="column column--10">
|
||||
<form>
|
||||
<div class="column column--3 column--med-10">
|
||||
<input type="radio" name="anonymous-or-channel" id="anonymous-select" class="input-radio" value="anonymous" {{#unless user}}checked {{/unless}} onchange="toggleChannel(event.target.value)"/>
|
||||
<label class="label label--pointer" for="anonymous-select">Anonymous</label>
|
||||
<input type="radio" name="anonymous-or-channel" id="anonymous-radio" class="input-radio" value="anonymous" {{#unless user}}checked {{/unless}} onchange="toggleChannel(event.target.value)"/>
|
||||
<label class="label label--pointer" for="anonymous-radio">Anonymous</label>
|
||||
</div><div class="column column--7 column--med-10">
|
||||
<input type="radio" name="anonymous-or-channel" id="in-a-channel-select" class="input-radio" value="in a channel" {{#if user}}checked {{/if}} onchange="toggleChannel(event.target.value)"/>
|
||||
<label class="label label--pointer" for="in-a-channel-select">In a channel</label>
|
||||
<input type="radio" name="anonymous-or-channel" id="channel-radio" class="input-radio" value="in a channel" {{#if user}}checked {{/if}} onchange="toggleChannel(event.target.value)"/>
|
||||
<label class="label label--pointer" for="channel-radio">In a channel</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue