closes #707, closes #686

This commit is contained in:
Baris Soner Usakli
2013-12-31 17:01:51 -05:00
parent 9d452241ad
commit d43f3cebc6
14 changed files with 116 additions and 29 deletions

4
app.js
View File

@@ -109,11 +109,11 @@
var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false; var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false;
utils.walk(path.join(__dirname, 'public/templates'), function (err, tplsToLoad) { utils.walk(path.join(__dirname, 'public/templates'), function (err, tplsToLoad) {
templates.init(tplsToLoad, customTemplates); templates.init(tplsToLoad, customTemplates);
}); });
plugins.ready(function() { plugins.ready(function() {
templates.ready(webserver.init); templates.ready(webserver.init);
}); });

View File

@@ -7,6 +7,7 @@
"location": "Location", "location": "Location",
"age": "Age", "age": "Age",
"joined": "Joined", "joined": "Joined",
"lastonline": "Last Online",
"profile_views": "Profile views", "profile_views": "Profile views",
"reputation": "Reputation", "reputation": "Reputation",
"posts": "Posts", "posts": "Posts",

View File

@@ -48,7 +48,6 @@ define(['taskbar'], function(taskbar) {
socket.emit('api:composer.push', { socket.emit('api:composer.push', {
pid: pid pid: pid
}, function(threadData) { }, function(threadData) {
console.log(threadData);
push({ push({
pid: pid, pid: pid,
title: threadData.title, title: threadData.title,
@@ -202,7 +201,7 @@ define(['taskbar'], function(taskbar) {
} }
}); });
postContainer.on('click', '.formatting-bar span .fa-picture-o', function() { postContainer.on('click', '.formatting-bar span .fa-picture-o, .formatting-bar span .fa-upload', function() {
$('#files').click(); $('#files').click();
}); });
@@ -213,6 +212,7 @@ define(['taskbar'], function(taskbar) {
loadFile(post_uuid, files[i]); loadFile(post_uuid, files[i]);
} }
} }
$('#fileForm')[0].reset();
}); });
@@ -317,7 +317,12 @@ define(['taskbar'], function(taskbar) {
} }
if(config.imgurClientIDSet) { if(config.imgurClientIDSet) {
postContainer.find('.upload-instructions').removeClass('hide') postContainer.find('.upload-instructions').removeClass('hide');
postContainer.find('.img-upload-btn').removeClass('hide');
}
if(config.allowFileUploads) {
postContainer.find('.file-upload-btn').removeClass('hide');
} }
postContainer.css('visibility', 'visible'); postContainer.css('visibility', 'visible');
@@ -469,36 +474,41 @@ define(['taskbar'], function(taskbar) {
} }
function loadFile(post_uuid, file) { function loadFile(post_uuid, file) {
if (!file.type.match('image.*')) {
return;
}
var reader = new FileReader(), var reader = new FileReader(),
dropDiv = $('#cmp-uuid-' + post_uuid).find('.imagedrop'); dropDiv = $('#cmp-uuid-' + post_uuid).find('.imagedrop');
$(reader).on('loadend', function(e) { $(reader).on('loadend', function(e) {
var bin = this.result.split(',')[1]; var regex = /^data:.*;base64,(.*)$/;
console.log(file);
var matches = this.result.match(regex);
var img = { var fileData = {
name: file.name, name: file.name,
data: bin data: matches[1]
}; };
createImagePlaceholder(post_uuid, img);
dropDiv.hide(); dropDiv.hide();
if(file.type.match('image.*')) {
uploadFile('api:posts.uploadImage', post_uuid, fileData);
} else {
if(file.size > parseInt(config.maximumFileSize, 10) * 1024) {
return composerAlert('File too big', 'Maximum allowed file size is ' + config.maximumFileSize + 'kbs');
}
uploadFile('api:posts.uploadFile', post_uuid, fileData);
}
}); });
reader.readAsDataURL(file); reader.readAsDataURL(file);
} }
function createImagePlaceholder(post_uuid, img) { function uploadFile(method, post_uuid, img) {
var postContainer = $('#cmp-uuid-' + post_uuid), var linkStart = method === 'api:posts.uploadImage' ? '!' : '',
postContainer = $('#cmp-uuid-' + post_uuid),
textarea = postContainer.find('textarea'), textarea = postContainer.find('textarea'),
text = textarea.val(), text = textarea.val(),
imgText = "![" + img.name + "](uploading...)"; imgText = linkStart + '[' + img.name + '](uploading...)';
text += imgText; text += imgText;
textarea.val(text + " "); textarea.val(text + " ");
@@ -509,18 +519,17 @@ define(['taskbar'], function(taskbar) {
composer.posts[post_uuid].uploadsInProgress.push(1); composer.posts[post_uuid].uploadsInProgress.push(1);
socket.emit("api:posts.uploadImage", img, function(err, data) { socket.emit(method, img, function(err, data) {
var currentText = textarea.val();
if(err) { if(err) {
textarea.val(currentText.replace(imgText, linkStart + '[' + img.name + '](upload error)'));
return app.alertError(err.message); return app.alertError(err.message);
} }
var currentText = textarea.val();
imgText = "![" + data.name + "](uploading...)";
if(!err) { textarea.val(currentText.replace(imgText, linkStart + '[' + data.name + '](' + data.url + ')'));
textarea.val(currentText.replace(imgText, "![" + data.name + "](" + data.url + ")"));
} else {
textarea.val(currentText.replace(imgText, "![" + data.name + "](upload error)"));
}
composer.posts[post_uuid].uploadsInProgress.pop(); composer.posts[post_uuid].uploadsInProgress.pop();
}); });
} }

View File

@@ -70,6 +70,10 @@
<span class="timeago" title="{joindate}"></span> <span class="timeago" title="{joindate}"></span>
<br/> <br/>
<span class="account-bio-label">[[user:lastonline]]</span>
<span class="timeago" title="{lastonline}"></span>
<br/>
<span class="account-bio-label">[[user:profile_views]]</span> <span class="account-bio-label">[[user:profile_views]]</span>
<span class="formatted-number">{profileviews}</span> <span class="formatted-number">{profileviews}</span>
<br/> <br/>

View File

@@ -121,6 +121,12 @@
<input type="checkbox" data-field="useOutgoingLinksPage"> <strong>Use Outgoing Links Warning Page</strong> <input type="checkbox" data-field="useOutgoingLinksPage"> <strong>Use Outgoing Links Warning Page</strong>
</label> </label>
</div> </div>
<div class="checkbox">
<label>
<input type="checkbox" data-field="allowFileUploads"> <strong>Allow users to upload regular files</strong>
</label>
</div>
<strong>Maximum File Size</strong><br /> <input type="text" class="form-control" value="2048" data-field="maximumFileSize"><br />
</div> </div>
</form> </form>

View File

@@ -7,10 +7,15 @@
<span class="btn btn-link" tabindex="-1"><i class="fa fa-italic"></i></span> <span class="btn btn-link" tabindex="-1"><i class="fa fa-italic"></i></span>
<span class="btn btn-link" tabindex="-1"><i class="fa fa-list"></i></span> <span class="btn btn-link" tabindex="-1"><i class="fa fa-list"></i></span>
<span class="btn btn-link" tabindex="-1"><i class="fa fa-link"></i></span> <span class="btn btn-link" tabindex="-1"><i class="fa fa-link"></i></span>
<span class="btn btn-link" tabindex="-1"> <span class="btn btn-link img-upload-btn hide" tabindex="-1">
<input type="file" id="files" name="files[]" multiple class="hide"/>
<i class="fa fa-picture-o"></i> <i class="fa fa-picture-o"></i>
</span> </span>
<span class="btn btn-link file-upload-btn hide" tabindex="-1">
<i class="fa fa-upload"></i>
</span>
<form id="fileForm">
<input type="file" id="files" name="files[]" multiple class="hide"/>
</form>
</div> </div>
<!-- <div class="btn btn-link pull-right">Preview</div> --> <!-- <div class="btn btn-link pull-right">Preview</div> -->
</div> </div>

View File

@@ -20,6 +20,7 @@ var request = require('request'),
try { try {
var response = JSON.parse(body); var response = JSON.parse(body);
if(response.success) { if(response.success) {
callback(null, response.data); callback(null, response.data);
} else { } else {

View File

@@ -212,6 +212,12 @@ var async = require('async'),
}, { }, {
field: 'allowRegistration', field: 'allowRegistration',
value: 1 value: 1
}, {
field: 'allowFileUploads',
value: 0,
}, {
filed: 'maximumFileSize',
value: 2048
}, { }, {
field: 'minimumTitleLength', field: 'minimumTitleLength',
value: 3 value: 3

View File

@@ -12,6 +12,8 @@ var db = require('./database'),
meta = require('./meta'), meta = require('./meta'),
async = require('async'), async = require('async'),
path = require('path'),
fs = require('fs'),
nconf = require('nconf'), nconf = require('nconf'),
validator = require('validator'), validator = require('validator'),
winston = require('winston'), winston = require('winston'),
@@ -358,6 +360,10 @@ var db = require('./database'),
Posts.uploadPostImage = function(image, callback) { Posts.uploadPostImage = function(image, callback) {
if(!meta.config.imgurClientID) {
return callback('imgurClientID not set', null);
}
if(!image) { if(!image) {
return callback('invalid image', null); return callback('invalid image', null);
} }
@@ -374,6 +380,37 @@ var db = require('./database'),
}); });
} }
Posts.uploadPostFile = function(file, callback) {
if(!meta.config.allowFileUploads) {
return callback('File uploads are not allowed');
}
if(!file) {
return callback('invalid file');
}
var buffer = new Buffer(file.data, 'base64');
if(buffer.length > parseInt(meta.config.maximumFileSize, 10) * 1024) {
return callback('File too big');
}
var filename = 'upload-' + utils.generateUUID() + path.extname(file.name);
var uploadPath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), filename);
fs.writeFile(uploadPath, buffer, function (err) {
if(err) {
callback(err.message, null);
} else {
callback(null, {
url: nconf.get('upload_url') + filename,
name: file.name
});
}
});
}
Posts.getPostsByUid = function(uid, start, end, callback) { Posts.getPostsByUid = function(uid, start, end, callback) {
user.getPostIds(uid, start, end, function(err, pids) { user.getPostIds(uid, start, end, function(err, pids) {
if(err) { if(err) {

View File

@@ -40,6 +40,8 @@ var path = require('path'),
config.useOutgoingLinksPage = meta.config.useOutgoingLinksPage; config.useOutgoingLinksPage = meta.config.useOutgoingLinksPage;
config.allowGuestPosting = meta.config.allowGuestPosting; config.allowGuestPosting = meta.config.allowGuestPosting;
config.allowRegistration = meta.config.allowRegistration || '1'; config.allowRegistration = meta.config.allowRegistration || '1';
config.allowFileUploads = meta.config.allowFileUploads;
config.maximumFileSize = meta.config.maximumFileSize;
config.emailSetup = !!meta.config['email:from']; config.emailSetup = !!meta.config['email:from'];
res.json(200, config); res.json(200, config);

View File

@@ -530,6 +530,11 @@ var fs = require('fs'),
user.getUserData(uid, function (err, data) { user.getUserData(uid, function (err, data) {
if (data) { if (data) {
data.joindate = new Date(parseInt(data.joindate, 10)).toISOString(); data.joindate = new Date(parseInt(data.joindate, 10)).toISOString();
if(data.lastonline) {
data.lastonline = new Date(parseInt(data.lastonline, 10)).toISOString();
} else {
data.lastonline = data.joindate;
}
if (!data.birthday) { if (!data.birthday) {
data.age = ''; data.age = '';

View File

@@ -14,7 +14,7 @@ var db = require('./database'),
Upgrade.check = function(callback) { Upgrade.check = function(callback) {
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
var latestSchema = new Date(2013, 11, 31).getTime(); var latestSchema = new Date(2014, 0, 1).getTime();
db.get('schemaDate', function(err, value) { db.get('schemaDate', function(err, value) {
if (parseInt(value, 10) >= latestSchema) { if (parseInt(value, 10) >= latestSchema) {

View File

@@ -183,6 +183,13 @@ var path = require('path'),
// Authentication Routes // Authentication Routes
auth.initialize(app); auth.initialize(app);
app.use(function(req, res, next) {
if(req.user) {
user.setUserField(req.user.uid, 'lastonline', Date.now());
}
next();
})
next(); next();
}, },
function(next) { function(next) {

View File

@@ -638,6 +638,10 @@ websockets.init = function(io) {
posts.uploadPostImage(data, callback); posts.uploadPostImage(data, callback);
}); });
socket.on('api:posts.uploadFile', function(data, callback) {
posts.uploadPostFile(data, callback);
});
socket.on('api:posts.getRawPost', function(data, callback) { socket.on('api:posts.getRawPost', function(data, callback) {
posts.getPostField(data.pid, 'content', function(err, raw) { posts.getPostField(data.pid, 'content', function(err, raw) {
callback({ callback({