diff --git a/app.js b/app.js index e06a85c..06ad078 100644 --- a/app.js +++ b/app.js @@ -15,11 +15,12 @@ var passport = require('passport') , FacebookStrategy = require('passport-facebook').Strategy; var routes = require('./routes/index'); +var login = require('./routes/login'); var chats = require('./routes/chats'); var users = require('./routes/users'); var posts = require('./routes/posts'); -var chat = require('./routes/chat'); var account = require('./routes/account'); +var learn = require('./routes/learn'); var app = express(); @@ -36,7 +37,7 @@ winston.add(winston.transports.File, { level: 'info' }); -mongoose.connect('mongodb://booklog3:123456@ds053130.mongolab.com:53130/booklog3'); +mongoose.connect('mongodb://booklog3:123456@ds047622.mongolab.com:47622/booklog3'); mongoose.connection.on('error', function() { winston.log('error', 'MongoDB: error'); }); @@ -45,8 +46,8 @@ mongoose.connection.on('open', function() { }); var postSchema = new mongoose.Schema({ - title : { type: String }, - content : { type: String }, + title: { type: String }, + content: { type: String }, userId: { type: mongoose.Schema.Types.ObjectId, ref: 'user' }, timeCreated: { type: Date, default: Date.now } }); @@ -59,13 +60,21 @@ var userSchema = new mongoose.Schema({ facebook: { type: Object, select: false } }); +var lessonSchema = new mongoose.Schema({ + lessonName: { type: String, unique: true }, + lessonLearn: { type: String, unique: true }, + timeCreated: { type: Date, default: Date.now } +}); + var Post = mongoose.model('post', postSchema); var User = mongoose.model('user', userSchema); +var Learn = mongoose.model('learn', lessonSchema); app.db = { model: { Post: Post, User: User, + Learn: Learn } }; @@ -94,8 +103,9 @@ passport.deserializeUser(function(obj, done) { }); passport.use(new FacebookStrategy({ - clientID: '1559480364270197', - clientSecret: '4d5d1e9389c179142348cbb7044bdab1', + clientID: '410866279063864', + clientSecret: '3887b8914b81d0e778d3b9af10775fb6', +// callbackURL: "http://alwaysladylove.com/auth/facebook/callback" callbackURL: "/auth/facebook/callback" }, function(accessToken, refreshToken, profile, done) { @@ -113,7 +123,6 @@ passport.use(new FacebookStrategy({ user = doc; } - console.log(user); return done(null, user); // verify callback }); @@ -124,22 +133,14 @@ passport.use(new FacebookStrategy({ app.use(cors()); app.use('/', routes); +app.use('/', login); app.use('/', posts); app.use('/', chats); app.use('/users', users); app.use('/account', account); +app.use('/learn', learn); -app.get('/login/facebook', - passport.authenticate('facebook')); - -app.get('/auth/facebook/callback', - passport.authenticate('facebook', { failureRedirect: '/login/fail' }), - function(req, res) { - // Successful authentication, redirect home. - res.redirect('/'); - }); - // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); @@ -179,4 +180,4 @@ app.use(function(err, req, res, next) { }); -module.exports = app; +module.exports = app; \ No newline at end of file diff --git a/bin/www b/bin/www index c141877..f3c5908 100755 --- a/bin/www +++ b/bin/www @@ -15,21 +15,33 @@ var WebSocketServer = require('websocket').server; * Get port from environment and store in Express. */ +/** + * Create HTTP server in worker process. + */ var port = normalizePort(process.env.PORT || '3000'); +var server = http.createServer(app); + +/* + * WebSocket Section + */ +var wsServer = new WebSocketServer({ + httpServer: server, + autoAcceptConnections: false +}); + +// create WebSocket connections array +app.clients = []; if (cluster.isMaster) { console.log('CPUs: ' + cpuCount); // Create a worker for each CPU for (var i = 0; i < cpuCount ; i++) { - cluster.fork({PORT: port + i}); + cluster.fork({ + PORT: port + i + }); } } else { - /** - * Create HTTP server in worker process. - */ - var port = process.env.PORT; - var server = http.createServer(app); console.log('HTTP server listening on port ' + port + ' at worker ' + cluster.worker.id); @@ -41,6 +53,8 @@ if (cluster.isMaster) { server.on('error', onError); server.on('listening', onListening); + wsServer.on('request', onWsRequest); + /* * WebSocket Section */ @@ -78,6 +92,28 @@ if (cluster.isMaster) { } +function onWsConnMessage(message) { + if (message.type == 'utf8') { + console.log('Received message: ' + message.utf8Data); + } else if (message.type == 'binary') { + console.log('Received binary data.'); + } +} + +function onWsConnClose(reasonCode, description) { + console.log(' Peer disconnected with reason: ' + reasonCode); +} + +function onWsRequest(request) { + var connection = request.accept('echo-protocol', request.origin); + console.log("WebSocket connection accepted."); + + app.clients.push(connection); + + connection.on('message', onWsConnMessage); + connection.on('close', onWsConnClose); +} + /** * Normalize a port into a number, string, or false. */ diff --git a/package.json b/package.json index e6e5540..9bc4907 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ "passport": "^0.2.2", "passport-facebook": "^2.0.0", "serve-favicon": "~2.2.1", + "websocket": "^1.0.21", "winston": "^1.0.1", - "websocket": "~1.0.21" + "nginx": "0.0.0", + "forever": "~0.15.1" } } diff --git a/public/booklog/index.html b/public/booklog/index.html index c781d66..2c48ab2 100644 --- a/public/booklog/index.html +++ b/public/booklog/index.html @@ -36,6 +36,20 @@

<%= content %>

+ + +
+ + + +
+
-

Jollen's 最新文章 +

afoo's 最新文章 Showcase Your Work

diff --git a/public/javascripts/app.js b/public/javascripts/app.js index b0c9d9c..9b3f4ec 100644 --- a/public/javascripts/app.js +++ b/public/javascripts/app.js @@ -9,10 +9,12 @@ var app = app || {}; **/ app.Message = Backbone.Model.extend({ url: function() { - return 'http://launchergap.org/1/post' +// return 'http://alwaysladylove.com/1/post' + return 'http://localhost:3000/1/post' + ( this.id === null ? '' : '/' + this.id ); }, id: null, + idAttribute: '_id', defaults: { success: false, errfor: {}, @@ -28,11 +30,13 @@ app.Message = Backbone.Model.extend({ app.ContentView = Backbone.View.extend({ el: '#content', events: { - 'click #subject': 'read' + 'click #subject': 'read', + 'click #delete': 'delete' }, // constructor initialize: function() { this.model = new app.Message(); + this.model.bind('sync', this.render, this); this.model.bind('change', this.render, this); this.template = _.template($('#post-list').html()); @@ -48,6 +52,19 @@ app.ContentView = Backbone.View.extend({ this.model.id = id; this.template = _.template($('#post-single').html()); this.model.fetch(); + }, + delete: function(evt){ + var self = this + + this.model.destroy({ + success: function(model, res){ + console.log('its deleted!'); + self.model.fetch(); + }, + error: function(model, res){ + console.log('delete error'); + } + }); } }); @@ -77,7 +94,22 @@ app.FormView = Backbone.View.extend({ } }); +app.LoginView = Backbone.View.extend({ + el: 'body', + events: { + 'click #op-modal': 'modal' + }, + render: function(){ + this.$('#myModal').modal(); + }, + modal: function(e){ + this.render(); + } +}); + + $(document).ready(function(){ app.contentView = new app.ContentView(); app.formView = new app.FormView(); -}); + app.loginView = new app.LoginView(); +}); \ No newline at end of file diff --git a/public/tolearn.js b/public/tolearn.js new file mode 100644 index 0000000..d102fdd --- /dev/null +++ b/public/tolearn.js @@ -0,0 +1,59 @@ +var app = app || {}; + +app.Lessons = Backbone.Model.extend({ + url: function(){ + return '/learn/lessons' + }, + defaults: { + errors: [], + errfor: {}, + lessons: [] + } +}); + +app.Lesson = Backbone.View.extend({ + url: function(){ + return '/learn/lessons/' + this.attributes.id + }, + id: '', + defaults: { + errors: [], + errfor: {}, + lesson: {} + } +}); + +app.ListView = Backbone.View.extend({ + el: '#tolearnlist', + template: _.template( $('#tmpl-tolearnlist').html() ), + events: {}, + initialize: function(){ + this.model = new app.Lessons(); + + this.listenTo(this.model, 'sync', this.render); + this.listenTo(this.model, 'change', this.render); + this.model.fetch(); + }, + render: function(){ + this.$el.html(this.template(this.model.attributes)); + } +}); + +app.LessonView = Backbone.View.extend({ + el: '#lessoninfo', + template: _.template( $('#tmpl-lessonlearn').html() ), + initialize: function(){ + this.model = new app.Lesson(); + this.listenTo(this.model, 'sync', this.render); + this.listenTo(this.model, 'change', this.render); + }, + render: function(){ + this.$el.html( this.template( this.model.attributes )); + } +}); + +$(document).ready(function(){ + app.listView = new app.ListView(); + app.lessonView = new app.LessonView(); +}); + diff --git a/routes/chat.js b/routes/chat.js deleted file mode 100644 index 5d27dbd..0000000 --- a/routes/chat.js +++ /dev/null @@ -1,47 +0,0 @@ -var express = require('express'); -var router = express.Router(); -var events = require('events'); - -var history = []; - -router.post('/send/:message', function(req, res, next) { - var workflow = new events.EventEmitter(); - var clients = req.app.clients; - - workflow.outcome = { - success: false, - errfor: {} - }; - - workflow.on('validation', function() { - history.push({ - message: req.params.message, - timestamp: new Date().getTime() - }); - workflow.emit('broadcast'); - }); - - workflow.on('broadcast', function() { - for (i = 0; i < clients.length; i++) { - var client = clients[i]; - var data = { - type: 'message', - data: history - }; - - console.log(data); - client.sendUTF(JSON.stringify(data)); - }; - - workflow.outcome.success = true; - workflow.emit('response'); - }); - - workflow.on('response', function() { - res.send(workflow.outcome); - }); - - workflow.emit('validation'); -}); - -module.exports = router; diff --git a/routes/learn.js b/routes/learn.js new file mode 100644 index 0000000..ba81bad --- /dev/null +++ b/routes/learn.js @@ -0,0 +1,33 @@ +var express = require('express'); +var router = express.Router(); + + +router.get('/', function(req, res, next){ + res.render('learn'); +}); + +router.get('/lessons', function(req, res, next){ + req.app.db.model.Learn + .find({}) + .exec(function(err, lessons){ + console.log(lessons); + res.send({ + lessons: lessons + }); + }); +}); + +router.post('/lessons', function(req, res, next){ + var lesson = req.app.db.model.Learn; + + var doc = new lesson({ + lessonName: req.query.lessonName, + lessonLearn: req.query.lessonLearn + }); + console.log(doc); + doc.save(); + + res.end(console.log("it's saved")); +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/login.js b/routes/login.js new file mode 100644 index 0000000..c22d1cc --- /dev/null +++ b/routes/login.js @@ -0,0 +1,23 @@ +var express = require('express'); +var router = express.Router(); +var passport = require('passport'); + + +/* FB auth */ + +router.get('/login/facebook', + passport.authenticate('facebook')); + +router.get('/auth/facebook/callback', + passport.authenticate('facebook', { failureRedirect: '/login' }), + function(req, res) { + // Successful authentication, redirect home. + res.redirect('/'); + }); + +router.get('/login', function(req, res, next){ + res.render('login', { title: 'Login', message: 'choose one you love!'}); +}); + + +module.exports = router; diff --git a/routes/posts.js b/routes/posts.js index e0540f9..21cb6f3 100644 --- a/routes/posts.js +++ b/routes/posts.js @@ -2,6 +2,7 @@ var express = require('express'); var router = express.Router(); var events = require('events'); var winston = require('winston'); +var cors = require('cors'); winston.add(winston.transports.File, { name: 'booklog3-1', @@ -13,8 +14,12 @@ winston.add(winston.transports.File, { function ensureAuthenticate(req, res, next) { if (req.isAuthenticated()) { winston.log('info', req.user.displayName); - return next(); } - res.redirect('/login/facebook'); + return next(); + } + + console.log('im not login'); + + res.redirect('/login'); } router.get('/1/post', function(req, res, next) { @@ -48,13 +53,14 @@ router.get('/1/post', function(req, res, next) { workflow.emit('validation'); }); -router.get('/1/post/:id', function(req, res, next) { +router.get('/1/post/:id', ensureAuthenticate, function(req, res, next) { + console.log('roger'); req.app.db.model.Post.findById(req.params.id, function(err, posts) { - res.json(posts); + res.json(posts); }); }); -router.post('/1/post', function(req, res, next) { +router.post('/1/post', ensureAuthenticate, function(req, res, next) { var workflow = new events.EventEmitter(); var Post = req.app.db.model.Post; @@ -102,20 +108,48 @@ router.post('/1/post', function(req, res, next) { }); router.delete('/1/post/:id', function(req, res, next) { - req.app.db.model.Post.findByIdAndRemove(req.params.id, function(err, posts) { - res.json(posts); + var workflow = new events.EventEmitter(); + var Post = req.app.db.model.Post; + + workflow.outcome = { + success: false, + errfor: {} + }; + + workflow.on('validation', function(){ + Post.findById(req.params.id, function(err, post){ + if(post === "undefined") { + workflow.outcome.errfor = "Article is't being found!"; + return workflow.emit('response'); + } + + workflow.emit('delete'); + }); + }); + + workflow.on('delete', function(){ + Post.findByIdAndRemove(req.params.id, function(err, posts) { + workflow.outcome.success = true; + workflow.emit('response'); + }); }); + + workflow.on('response', function(){ + res.send(workflow.outcome); + }); + + workflow.emit('validation'); }); router.put('/1/post/:id', function(req, res, next) { var fieldsToSet = { - title: req.query.title, - content: req.query.content + title: req.query.title, + content: req.query.content }; req.app.db.model.Post.findOneAndUpdate({_id: req.params.id}, fieldsToSet, function(err, post) { - res.json(post); + res.json(post); }); }); -module.exports = router; +module.exports = router; \ No newline at end of file diff --git a/views/learn.jade b/views/learn.jade new file mode 100644 index 0000000..d92497a --- /dev/null +++ b/views/learn.jade @@ -0,0 +1,47 @@ +extends layout + +block content + .row + .col-md-6.col-sm-6 + h2 To Learn list + div#tolearnlist + .col-md-6.col-sm-6 + h2 Lesson Info + div#lessoninfo + + script(type='text/template', id='tmpl-tolearnlist') + br + br + ul + <% _.each(lessons, function(lesson){ %> + li + a(href='#') <%= lesson.lessonName %> + <% }) %> + + script(type='text/template', id='tmpl-lessonlearn') + br + br + div.well.non-editable + .row + h2 <%= lesson.lessonName %> + h6 created on <%= lesson.createdTime %> + p <%= lesson.lessonlearn %> + button.btn.btn-primary.pull-right.btn.edit Edit + + div.well.editable.hide + .row + form + div.control-group + label Lesson Name: + div.controls + input.form-control(type='text', name='lessonname', value!='<%= lesson.lessonName %>') + br + div + button.btn.btn-large.btn-info.btn.save('type=button') Save + button.btn.btn-large.btn-info.btn.cancel('type=button') Cancel + + script(src='javascripts/jquery.min.js') + script(src='javascripts/bootstrap.min.js') + script(src='vendor/underscore/underscore-min.js') + script(src='vendor/backbone/backbone-min.js') + script(src='tolearn.js', type='text/javascript') \ No newline at end of file diff --git a/views/login.jade b/views/login.jade new file mode 100644 index 0000000..5450012 --- /dev/null +++ b/views/login.jade @@ -0,0 +1,18 @@ +extends layout + +block content + h1= title + h4= message + div.row + a(href='/login/facebook') + img(src='https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_facebook_box_blue.png') + a(href='') + img(src='https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_twitter_box_white.png') + a(href='') + img(src='https://cdn0.iconfinder.com/data/icons/yooicons_set01_socialbookmarks/128/social_google_box.png') + + script(src='javascripts/jquery.min.js') + script(src='javascripts/bootstrap.min.js') + script(src='vendor/underscore/underscore-min.js') + script(src='vendor/backbone/backbone-min.js') + script(src='javascripts/app.js')