From 195505cf5e14e945028414e3f0b6d7f37d362004 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Allan=20M=C3=B8rk=20Christensen?=
Date: Thu, 13 Jun 2013 22:50:04 +0200
Subject: [PATCH] Initial commit of Web application file structure, and some
in-progress API support for user handling.
---
.gitignore | 3 +
README.md | 41 +++-
app.js | 54 +++++
oauth.txt => documentation/oauth.txt | 0
rest api.txt => documentation/rest api.txt | 0
models/project.js | 15 ++
models/user.js | 48 +++++
package.json | 30 +++
public/favicon.ico | Bin 0 -> 2809 bytes
public/stylesheets/style.css | 8 +
routes/index.js | 25 +++
routes/passport.js | 218 +++++++++++++++++++++
routes/project.js | 15 ++
routes/user.js | 90 +++++++++
views/account.ejs | 3 +
views/index.ejs | 7 +
views/layout.ejs | 23 +++
views/login.ejs | 24 +++
views/new-user.ejs | 28 +++
19 files changed, 630 insertions(+), 2 deletions(-)
create mode 100644 .gitignore
create mode 100644 app.js
rename oauth.txt => documentation/oauth.txt (100%)
rename rest api.txt => documentation/rest api.txt (100%)
create mode 100644 models/project.js
create mode 100644 models/user.js
create mode 100644 package.json
create mode 100644 public/favicon.ico
create mode 100644 public/stylesheets/style.css
create mode 100644 routes/index.js
create mode 100644 routes/passport.js
create mode 100644 routes/project.js
create mode 100644 routes/user.js
create mode 100644 views/account.ejs
create mode 100644 views/index.ejs
create mode 100644 views/layout.ejs
create mode 100644 views/login.ejs
create mode 100644 views/new-user.ejs
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..727b0c103
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+config
+.idea
\ No newline at end of file
diff --git a/README.md b/README.md
index db583ae32..12b99ea53 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,41 @@
-scripler
+Scripler
========
+The Scripler web application source code repository.
-The Scripler web application source code repository
\ No newline at end of file
+Folder Structure
+----------------
+
+* documentation
+ * Early documentation drafts of the API
+* public
+ * Static files to be deliveredserved through the Web server
+* views
+ * Dynamic templates that needs rendering before being served from the Web server
+* config
+ * Configuration files for the Node.js server
+* models
+ * The MongoDB schemas for the collections
+* routes
+ * Application logic for the different logical domains
+
+Requirements
+------------
+ * [MongoDB][1]
+ * [Node.js][2] 10.0+
+
+Installation
+------------
+ npm install
+
+How To Run
+----------
+ node app.js
+
+
+Bcrypt Installation Problems
+----------------------------
+Ask for a pre-build module, or follow the guide:
+https://github.com/ncb000gt/node.bcrypt.js/#dependencies
+
+ [1]: http://www.mongodb.org/
+ [2]: http://nodejs.org/
\ No newline at end of file
diff --git a/app.js b/app.js
new file mode 100644
index 000000000..b352ed874
--- /dev/null
+++ b/app.js
@@ -0,0 +1,54 @@
+var express = require('express')
+ , index = require('./routes/index')
+ , user = require('./routes/user')
+ , http = require('http')
+ , path = require('path')
+ , mongoose = require('mongoose')
+ , conf = require('config')
+ , passport = require('passport')
+ , scriplerPassport = require('./routes/passport');
+
+var app = express();
+
+// db connect
+mongoose.connect(conf.db.uri);
+
+// all environments
+app.set('port', conf.app.port);
+app.set('views', __dirname + '/views');
+app.set('view engine', 'ejs');
+app.engine('ejs', require('ejs-locals'));
+app.use(express.logger('dev'));
+app.use(express.bodyParser());
+app.use(express.methodOverride());
+app.use(express.cookieParser(conf.app.cookie_secret));
+app.use(express.session({ secret: conf.app.session_secret }));
+app.use(passport.initialize());
+app.use(passport.session());
+app.use(app.router);
+app.use(express.static(path.join(__dirname, 'public')));
+
+// development only
+if ('development' == app.get('env')) {
+ app.use(express.errorHandler());
+}
+
+/*Dummy GUI*/
+//app.get('/', index.index);
+//app.get('/account', index.account);
+//app.get('/login', index.login);
+//app.post('/login', user.login);
+//app.get('/new-user', index.newUser);
+//app.post('/new-user', index.newUserPost);
+
+/*API*/
+app.get('/users', user.list);
+app.post('/user/login', user.login);
+app.post('/user/logout', user.logout);
+app.post('/user/register', user.register);
+
+scriplerPassport.initPaths(app);
+
+http.createServer(app).listen(app.get('port'), function () {
+ console.log('Express server listening on port ' + app.get('port') + ('development' == app.get('env') ? ' - in development mode!' : ''));
+});
diff --git a/oauth.txt b/documentation/oauth.txt
similarity index 100%
rename from oauth.txt
rename to documentation/oauth.txt
diff --git a/rest api.txt b/documentation/rest api.txt
similarity index 100%
rename from rest api.txt
rename to documentation/rest api.txt
diff --git a/models/project.js b/models/project.js
new file mode 100644
index 000000000..80bb65157
--- /dev/null
+++ b/models/project.js
@@ -0,0 +1,15 @@
+var mongoose = require('mongoose')
+ , Schema = mongoose.Schema
+ , bcrypt = require('bcrypt')
+ , SALT_WORK_FACTOR = 10;
+
+/**
+ * User DB
+ */
+var ProjectSchema = new Schema({
+ name: { type: String, required: true },
+ order: { type: Number},
+ modified: { type: Date, default: Date.now }
+});
+
+exports.Project = mongoose.model('Project', ProjectSchema);
\ No newline at end of file
diff --git a/models/user.js b/models/user.js
new file mode 100644
index 000000000..bac82f0a7
--- /dev/null
+++ b/models/user.js
@@ -0,0 +1,48 @@
+var mongoose = require('mongoose')
+ , Schema = mongoose.Schema
+ , bcrypt = require('bcrypt')
+ , SALT_WORK_FACTOR = 10;
+
+/**
+ * User DB
+ */
+var UserSchema = new Schema({
+ name: { type: String, required: true },
+ email: { type: String, required: true, unique: true },
+ password: { type: String, required: true },
+ providers: [ {} ],
+ modified: { type: Date, default: Date.now }
+});
+
+/** Handle bcrypt password-hashing.
+ * Source: http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt
+ */
+UserSchema.pre('save', function (next) {
+ var user = this;
+
+ // only hash the password if it has been modified (or is new)
+ if (!user.isModified('password')) return next();
+
+ // generate a salt
+ bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
+ if (err) return next(err);
+
+ // hash the password along with our new salt
+ bcrypt.hash(user.password, salt, function (err, hash) {
+ if (err) return next(err);
+
+ // override the cleartext password with the hashed one
+ user.password = hash;
+ next();
+ });
+ });
+});
+
+UserSchema.methods.comparePassword = function (candidatePassword, cb) {
+ bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
+ if (err) return cb(err);
+ cb(null, isMatch);
+ });
+};
+
+exports.User = mongoose.model('User', UserSchema);
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..578297c07
--- /dev/null
+++ b/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "scripler-server",
+ "description": "Scripler Server",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "start": "node app.js"
+ },
+ "dependencies": {
+ "express": "3.2.4",
+ "config": "~0.4.25",
+ "mongoose": "~3.6.11",
+ "ejs": "~0.8.4",
+ "ejs-locals": "~1.0.2",
+ "bcrypt": "~0.7.6",
+ "passport": "~0.1.17",
+ "passport-twitter": "~0.1.5",
+ "passport-facebook": "~0.1.5",
+ "passport-linkedin": "~0.1.3",
+ "passport-google": "~0.3.0",
+ "passport-local": "~0.1.6",
+ "xtend": "~2.0.5"
+ },
+ "readmeFilename": "README.md",
+ "main": "app.js",
+ "devDependencies": {},
+ "repository": "",
+ "author": "",
+ "license": "BSD"
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..032dc84a2e7aedf2b636d23c45ef0845aceafc0d
GIT binary patch
literal 2809
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
+User:
+<%= user %>
\ No newline at end of file
diff --git a/views/index.ejs b/views/index.ejs
new file mode 100644
index 000000000..e5816115e
--- /dev/null
+++ b/views/index.ejs
@@ -0,0 +1,7 @@
+<% layout('layout') -%>
+Scripler
+<% if (!user) { %>
+ You're not supposed to be here. Visit Scripler .
+<% } else { %>
+ Hello, <%= user.name %>.
+<% } %>
\ No newline at end of file
diff --git a/views/layout.ejs b/views/layout.ejs
new file mode 100644
index 000000000..3f583c50f
--- /dev/null
+++ b/views/layout.ejs
@@ -0,0 +1,23 @@
+
+
+
+ Scripler
+
+
+
+ <% if (!user) { %>
+ Home |
+ Log In |
+ Create User
+
+ <% } else { %>
+
+ Home |
+ Account |
+ Add another login |
+ Log Out
+
+ <% } %>
+ <%- body %>
+
+
\ No newline at end of file
diff --git a/views/login.ejs b/views/login.ejs
new file mode 100644
index 000000000..9ee95d791
--- /dev/null
+++ b/views/login.ejs
@@ -0,0 +1,24 @@
+<% layout('layout') -%>
+Select login-provider:
+Sign in with Twitter
+Sign in with Facebook
+Sign in with Google
+Sign in with LinkedIn
+
+Or login with a local account:
+
\ No newline at end of file
diff --git a/views/new-user.ejs b/views/new-user.ejs
new file mode 100644
index 000000000..01ee509d4
--- /dev/null
+++ b/views/new-user.ejs
@@ -0,0 +1,28 @@
+<% layout('layout') -%>
+Select login-provider:
+Sign in with Twitter
+Sign in with Facebook
+Sign in with Google
+Sign in with LinkedIn
+
+Or create a new local account:
+
\ No newline at end of file