diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ed1f710 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "node_modules/mmh"] + path = node_modules/mmh + url = https://cr0@github.com/cr0/mmh.git diff --git a/assets/.gitkeep b/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/config.sample.yml b/config.sample.yml deleted file mode 100644 index 6caaa7e..0000000 --- a/config.sample.yml +++ /dev/null @@ -1,20 +0,0 @@ -default: - - baseurl: 'http://localhost:3000' - - mongodb: - port: 27017 - host: '127.0.0.1' - passwort: '' - - oauth: - google: - clientId: '' - secret: '' - facebook: - clientId: '' - secret: '' - amazon: - clientId: '' - secret: '' - diff --git a/config/extensions.coffee b/config/extensions.coffee new file mode 100644 index 0000000..fef3e18 --- /dev/null +++ b/config/extensions.coffee @@ -0,0 +1,6 @@ +module.exports = + + passport: + enabled: yes + model: 'User' + provider: ['amazon', 'google', 'facebook'] \ No newline at end of file diff --git a/config/policies.coffee b/config/policies.coffee new file mode 100644 index 0000000..7d15c74 --- /dev/null +++ b/config/policies.coffee @@ -0,0 +1,11 @@ +module.exports = + # true = allow, false = deny, function = evaluate + + '*': true + + 'FooController': + '*': 'authenticated' + + 'UserController': + '*': true + 'me': 'authenticated' \ No newline at end of file diff --git a/config/routes.coffee b/config/routes.coffee new file mode 100644 index 0000000..71c14a0 --- /dev/null +++ b/config/routes.coffee @@ -0,0 +1,16 @@ +module.exports = + + '/': 'home#index' + '/login': 'home#index' + '/logout': 'home#index' + '/imprint': 'home#index' + '/gallery': 'home#index' + '/settings': 'home#index' + + '/auth/req': 'auth#required' + '/auth/failed': 'auth#failed' + '/auth/logout': 'auth#logout' + + '/auth/:provider/callback': 'auth#validate' + + '/user/me': 'user#me' diff --git a/node_modules/mmh b/node_modules/mmh new file mode 160000 index 0000000..6c61d9d --- /dev/null +++ b/node_modules/mmh @@ -0,0 +1 @@ +Subproject commit 6c61d9d206e94701642520f97a38b666d66da691 diff --git a/package.json b/package.json index 72cc790..f6d6129 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "node-galerie", + "private": true, "version": "0.0.0", "description": "a gallery written in node, nothing more.", "main": "server.js", @@ -9,6 +10,7 @@ "scripts": { "install": "grunt build", "test": "grunt test", + "start": "node start.js", "blanket": { "pattern": [ ".test" @@ -29,24 +31,12 @@ "readmeFilename": "README.md", "dependencies": { "coffee-script": "1.6.x", - "express": "3.x", - "mongoose": "3.6.x", - "jade": "0.33.x", "grunt": "0.4.x", "grunt-cli": "0.1.x", "grunt-contrib-coffee": "0.7.x", "grunt-contrib-clean": "0.5.x", - "passport": "0.1.x", - "passport-amazon": "0.1.x", - "passport-google-oauth": "0.1.x", - "passport-facebook": "0.1.x", - "passport-local": "0.1.x", - "yaml-config": "0.2.x", - "connect-ensure-login": "0.1.x", - "basic-auth-mongoose": "0.1.x", - "mongoose-schema-extend": "0.1.x", "source-map-support": "0.2.x", - "jquery-file-upload-middleware": "0.0.8" + "mongoose": "3.6.x" }, "devDependencies": { "grunt-contrib-watch": "0.5.x", diff --git a/server.js b/server.js deleted file mode 100644 index c369065..0000000 --- a/server.js +++ /dev/null @@ -1,7 +0,0 @@ - -var App = require('./app'); -require('source-map-support').install(); - -app = new App(); -app.routes(); -app.start(); diff --git a/src/.gitkeep b/src/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/index.coffee b/src/index.coffee deleted file mode 100644 index 719c982..0000000 --- a/src/index.coffee +++ /dev/null @@ -1,98 +0,0 @@ -express = require 'express' -fs = require 'fs' -path = require 'path' -passport = require 'passport' -mongoose = require 'mongoose' -upload = require 'jquery-file-upload-middleware' - -AmazonOauth = require './util/amazon-oauth' -FacebookOauth = require './util/facebook-oauth' -GoogleOauth = require './util/google-oauth' -LocalOauth = require './util/local-oauth' - -class App - EXPRESS: express() - - constructor: -> - @port = 3000 - - @_setConfig() - @_setOauth() - @_upload() - - mongoose.connect 'mongodb://localhost/test' - - - routes: -> - @_includeRoute file for file in fs.readdirSync __dirname + '/routes/' when file.endsWith '-route.js' - - # sourcemap route - @EXPRESS.all /^\/assets\/(.*)$/, (req, res) -> - res.redirect req.params[0]; - - # create 404 route - @EXPRESS.all '*', (req, res) -> - if req.xhr - res.json - error: - code: 404 - message: "route not found" - , 404 - else - res.render 'home' - - - start: -> - @EXPRESS.listen @port, => - console.log "Listening on #{@port}\nPress CTRL-C to stop server." - - - _upload: -> - upload.configure - uploadDir: process.cwd() + '/public/uploads' - uploadUrl: '/uploads' - imageVersions: - thumbnail: - width: 80 - height: 80 - - _includeRoute: (file) -> - try - route = require './routes/' + file - (new route @EXPRESS).setup() - catch err - console.error "Error adding route from #{file}: #{err}" - - - _setConfig: -> - @EXPRESS.use express.static(process.cwd() + '/public') - @EXPRESS.use express.static(process.cwd() + '/assets') - @EXPRESS.use '/upload', upload.fileHandler() - @EXPRESS.use express.bodyParser() - @EXPRESS.use express.favicon() - @EXPRESS.use express.logger('dev') - - @EXPRESS.use express.cookieParser() - @EXPRESS.use express.session - secret: 'node-galerie' - - @EXPRESS.set 'view engine', 'jade' - - - _setOauth: -> - @EXPRESS.use passport.initialize() - @EXPRESS.use passport.session() - - try - new AmazonOauth() - new FacebookOauth() - new GoogleOauth() - new LocalOauth() - catch err - console.error "Error adding oauth: #{err}" - - -module.exports = App - -String::beginsWith = (str) -> if @match(new RegExp "^#{str}") then true else false -String::endsWith = (str) -> if @match(new RegExp "#{str}$") then true else false diff --git a/src/models/album.coffee b/src/models/album.coffee deleted file mode 100644 index 896db88..0000000 --- a/src/models/album.coffee +++ /dev/null @@ -1,44 +0,0 @@ - -mongoose = require 'mongoose' - - -schema = new mongoose.Schema - - type: - type: String - default: 'album' - - name: - type: String - required: true - unique: true - - description: - type: String - unique: true - - tags: - type: String - - 'location.lat': Number - 'location.lng': Number - - from: [ - id: - type: mongoose.Schema.Types.ObjectId - ref: 'BaseUser' - required: true - - name: - type: String - required: true - ] - - visible: [ - type: mongoose.Schema.Types.ObjectId - ] - - -, collection : 'gallery' - -module.exports = mongoose.model 'Album', schema \ No newline at end of file diff --git a/src/models/role.coffee b/src/models/role.coffee deleted file mode 100644 index 8d69320..0000000 --- a/src/models/role.coffee +++ /dev/null @@ -1,19 +0,0 @@ - -mongoose = require 'mongoose' - - -schema = new mongoose.Schema - - type: - type: String - default: 'role' - - name: - type: String - required: true - unique: true - - -, collection : 'gallery' - -module.exports = mongoose.model 'Role', schema \ No newline at end of file diff --git a/src/models/user.coffee b/src/models/user.coffee deleted file mode 100644 index e5c5d47..0000000 --- a/src/models/user.coffee +++ /dev/null @@ -1,68 +0,0 @@ - -mongoose = require 'mongoose' -basicAuth = require 'basic-auth-mongoose' -extend = require 'mongoose-schema-extend' - - -BaseUserSchema = new mongoose.Schema - - type: - type: String - default: 'user' - - email: - type: String - required: true - - name: - type: String - required: true - - username: String - - albums: [ - id: - type: mongoose.Schema.Types.ObjectId - ref: 'Gallery' - - name: - type: String - required: true - ] - - roles: [ - name: - type: String - ] - -, collection : 'gallery' - - -LocalUserSchema = BaseUserSchema.extend - - 'provider.name': - type: String - default: 'local' - - verified: Boolean - - -OauthUserSchema = BaseUserSchema.extend - - 'provider.name': - type: String - required: true - - 'provider.id': - type: String - required: true - - -# add 'username' and salted 'password' -LocalUserSchema.plugin basicAuth - -BaseUser = mongoose.model 'BaseUser', BaseUserSchema -LocalUser = mongoose.model 'LocalUser', LocalUserSchema -OauthUser = mongoose.model 'OauthUser', OauthUserSchema - -module.exports = {LocalUser, OauthUser, BaseUser} \ No newline at end of file diff --git a/src/routes/album-route.coffee b/src/routes/album-route.coffee deleted file mode 100644 index 115cad9..0000000 --- a/src/routes/album-route.coffee +++ /dev/null @@ -1,85 +0,0 @@ - -ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn - -Route = require './' - -Album = require '../models/album' - - -class AlbumRoute extends Route - - setup: -> - - @app.get '/api/album/:id', ensureLoggedIn('/login'), (req, res) -> - Album.findById req.params.id, (err, album) -> - if not err - res.statusCode = 201 - res.json - code: 'ok' - type: 'album' - data: album - else - res.statusCode = 500 - res.json - code: 'error' - type: 'album' - error: err - - @app.put '/api/album/:id', ensureLoggedIn('/login'), (req, res) -> - Album.findByIdAndUpdate req.params.id, {"$set":req.body}, (err, album) -> - if not err - res.statusCode = 201 - res.json - code: 'ok' - type: 'album' - data: album - else - res.statusCode = 500 - res.json - code: 'error' - type: 'album' - error: err - - @app.delete '/api/album/:id', ensureLoggedIn('/login'), (req, res) -> - Album.findByIdAndRemove req.params.id, (err) -> - if not err - res.statusCode = 201 - res.json - code: 'ok' - type: 'album' - data: [] - else - res.statusCode = 500 - res.json - code: 'error' - type: 'album' - error: err - - @app.get '/api/album', ensureLoggedIn('/login'), (req, res) -> - Album.find - type: 'album' - , (err, albums) -> - res.json - code: 'ok' - type: 'album' - count: albums.length - data: albums - - @app.post '/api/album', ensureLoggedIn('/login'), (req, res) -> - album = new Album req.body - album.save (err, album) -> - if not err - res.statusCode = 201 - res.json - code: 'ok' - type: 'album' - data: album - else - res.statusCode = 500 - res.json - code: 'error' - type: 'album' - error: err - - -module.exports = AlbumRoute \ No newline at end of file diff --git a/src/routes/auth-route.coffee b/src/routes/auth-route.coffee deleted file mode 100644 index c8e47cf..0000000 --- a/src/routes/auth-route.coffee +++ /dev/null @@ -1,76 +0,0 @@ - -passport = require 'passport' - -Route = require './' - -class AuthRoute extends Route - - setup: -> - - # google - @app.all '/auth/google', passport.authenticate 'google', scope: [ - 'https://www.googleapis.com/auth/userinfo.profile', - 'https://www.googleapis.com/auth/userinfo.email' - ] - @app.all '/auth/google/callback', passport.authenticate 'google', - failureRedirect: '/auth/failed' - successRedirect: '/auth/success' - - # facebook - @app.all '/auth/facebook', passport.authenticate 'facebook', scope: ['email'], display: 'popup' - @app.all '/auth/facebook/callback', passport.authenticate 'facebook', - failureRedirect: '/auth/failed' - successRedirect: '/auth/success' - - # amazon - @app.all '/auth/amazon', passport.authenticate 'amazon', scope: ['profile'] - @app.all '/auth/amazon/callback', passport.authenticate 'amazon', - failureRedirect: '/auth/failed' - successRedirect: '/auth/success' - - # local - @app.all '/auth/local', passport.authenticate 'local', - failureRedirect: '/auth/failed' - successRedirect: '/auth/success' - - @app.all '/auth/logout', (req, res) -> - req.logout() - res.status 200 - if req.xhr then res.json - code: 200 - message: 'logout successful' - else res.redirect '/' - - # auth req - @app.all '/auth/req', (req, res) -> - res.status 401 - if req.xhr then res.json - error: - code: 401 - message: 'login required' - else - res.render 'error', - error: - code: 401 - message: 'login required' - - # auth req - @app.all '/auth/success', (req, res) -> - res.status 200 - if req.xhr then res.redirect '/user/me' - else res.render 'success' - - # error - @app.all '/auth/failed', (req, res) -> - res.status 401 - if req.xhr then res.json - error: - code: 401 - message: 'login failed' - else res.render 'error', - error: - code: 401 - message: 'login failed' - - -module.exports = AuthRoute \ No newline at end of file diff --git a/src/routes/index.coffee b/src/routes/index.coffee deleted file mode 100644 index ca08837..0000000 --- a/src/routes/index.coffee +++ /dev/null @@ -1,12 +0,0 @@ - -ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn - - -class Route - constructor: (@app) -> - - setup: -> - throw Error 'not implemented' - - -module.exports = Route \ No newline at end of file diff --git a/src/routes/main-route.coffee b/src/routes/main-route.coffee deleted file mode 100644 index a45bfde..0000000 --- a/src/routes/main-route.coffee +++ /dev/null @@ -1,12 +0,0 @@ - -Route = require './' - - -class MainRoute extends Route - - setup: -> - @app.all '/', (req, res) -> - res.render 'home' - - -module.exports = MainRoute \ No newline at end of file diff --git a/src/routes/user-route.coffee b/src/routes/user-route.coffee deleted file mode 100644 index ebea0ff..0000000 --- a/src/routes/user-route.coffee +++ /dev/null @@ -1,24 +0,0 @@ - -ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn - -Route = require './' - - -class UserRoute extends Route - - setup: -> - @app.all '/user/me', ensureLoggedIn('/auth/req'), (req, res) -> - res.json - _id: req.user.id - type: req.user.type - name: req.user.name - username: req.user.username - email: req.user.email - provider: req.user.provider - albums: req.user.albums - roles: req.user.roles - groups: [] - loggedin: true - - -module.exports = UserRoute \ No newline at end of file diff --git a/src/util/amazon-oauth.coffee b/src/util/amazon-oauth.coffee deleted file mode 100644 index 01dc182..0000000 --- a/src/util/amazon-oauth.coffee +++ /dev/null @@ -1,27 +0,0 @@ -passport = require 'passport' -AmazonStrategy = require('passport-amazon').Strategy - -Config = require './config' -Oauth = require './oauth' - - -class AmazonOauth extends Oauth - - constructor: -> - super() - passport.use @_createStrategy() - - - _createStrategy: -> - config = Config.getInstance().get() - - new AmazonStrategy - clientID: config.oauth.amazon.clientId, - clientSecret: config.oauth.amazon.secret, - callbackURL: config.baseurl + '/auth/amazon/callback' - , (accessToken, refreshToken, profile, done) => - console.log "Got accesstoken #{accessToken} and a profile", profile - @_findOauthUser 'amazon', profile, done - - -module.exports = AmazonOauth \ No newline at end of file diff --git a/src/util/config.coffee b/src/util/config.coffee deleted file mode 100644 index f8675c3..0000000 --- a/src/util/config.coffee +++ /dev/null @@ -1,16 +0,0 @@ - -config = require 'yaml-config' - -Singleton = require './singleton' - - -class Config extends Singleton - - constructor: -> - @_config = config.readConfig(process.cwd() + '/config.yml'); - - get: -> - @_config - - -module.exports = Config \ No newline at end of file diff --git a/src/util/facebook-oauth.coffee b/src/util/facebook-oauth.coffee deleted file mode 100644 index 69f8495..0000000 --- a/src/util/facebook-oauth.coffee +++ /dev/null @@ -1,27 +0,0 @@ -passport = require 'passport' -FacebookStrategy = require('passport-facebook').Strategy - -Config = require './config' -Oauth = require './oauth' - - -class FacebookOauth extends Oauth - - constructor: -> - super() - passport.use @_createStrategy() - - - _createStrategy: -> - config = Config.getInstance().get() - - new FacebookStrategy - clientID: config.oauth.facebook.clientId, - clientSecret: config.oauth.facebook.secret, - callbackURL: config.baseurl + '/auth/facebook/callback' - , (accessToken, refreshToken, profile, done) => - console.log "Got accesstoken #{accessToken} and a profile", profile - @_findOauthUser 'facebook', profile, done - - -module.exports = FacebookOauth \ No newline at end of file diff --git a/src/util/google-oauth.coffee b/src/util/google-oauth.coffee deleted file mode 100644 index 0c143db..0000000 --- a/src/util/google-oauth.coffee +++ /dev/null @@ -1,27 +0,0 @@ -passport = require 'passport' -GoogleStrategy = require('passport-google-oauth').OAuth2Strategy - -Config = require './config' -Oauth = require './oauth' - - -class GoogleOauth extends Oauth - - constructor: -> - super() - passport.use @_createStrategy() - - - _createStrategy: -> - config = Config.getInstance().get() - - new GoogleStrategy - clientID: config.oauth.google.clientId, - clientSecret: config.oauth.google.secret, - callbackURL: config.baseurl + '/auth/google/callback' - , (accessToken, refreshToken, profile, done) => - console.log "Got accesstoken #{accessToken} and a profile", profile - @_findOauthUser 'google', profile, done - - -module.exports = GoogleOauth \ No newline at end of file diff --git a/src/util/local-oauth.coffee b/src/util/local-oauth.coffee deleted file mode 100644 index 214429a..0000000 --- a/src/util/local-oauth.coffee +++ /dev/null @@ -1,33 +0,0 @@ -passport = require 'passport' -LocalStrategy = require('passport-local').Strategy - -Config = require './config' -Oauth = require './oauth' - -LocalUser = require '../models/user' - - -class FacebookOauth extends Oauth - - constructor: -> - super() - passport.use @_createStrategy() - - - _createStrategy: -> - config = Config.getInstance().get() - - new LocalStrategy (username, password, done) -> - LocalUser.findOne - nickname: username - , (err, user) -> - if err - console.log "unknown user" - done error - if not user?.authenticate password - done null, false - - done null, user - - -module.exports = FacebookOauth \ No newline at end of file diff --git a/src/util/oauth.coffee b/src/util/oauth.coffee deleted file mode 100644 index 3074c30..0000000 --- a/src/util/oauth.coffee +++ /dev/null @@ -1,57 +0,0 @@ - -passport = require 'passport' - -{LocalUser, OauthUser, BaseUser} = require '../models/user' -Role = require '../models/role' - - -class Oauth - - @INITIALIZED: false - - constructor: -> - if not @INITIALIZED - passport.serializeUser (user, done) -> - done null, user.id - - passport.deserializeUser (id, done) -> - LocalUser.findById id, (err, user) -> - return done err, user if not err - OauthUser .findById id, (err, user) -> - return done err, user if not err - - @INITIALIZED = true - - - _findOauthUser: (providerName, profile, done) -> - OauthUser.findOne - 'provider.name': providerName - 'provider.id': profile.id - , (err, user) -> - if user - console.log "got user from db #{user}" - done null, user - else - BaseUser.count - email: profile.emails[0]?.value - , (err, count) -> - if count > 0 - done null, false, { message: 'Email address already in use' } - else - user = new OauthUser - name: profile.displayName - username: profile.username - email: profile.emails[0]?.value - 'provider.id': profile.id - 'provider.name': providerName - roles: [ - name: 'user' - , - name: 'oauth' - ] - user.save (err) -> - console.log "stored user in db #{user}" - done null, user if not err - - -module.exports = Oauth \ No newline at end of file diff --git a/src/util/singleton.coffee b/src/util/singleton.coffee deleted file mode 100644 index de6cf09..0000000 --- a/src/util/singleton.coffee +++ /dev/null @@ -1,12 +0,0 @@ - -class Singleton - instance = null - - @getInstance: -> - if not @instance? - instance = new @ - - instance - - -module.exports = Singleton \ No newline at end of file diff --git a/start.js b/start.js new file mode 100644 index 0000000..65842bb --- /dev/null +++ b/start.js @@ -0,0 +1,4 @@ +require( 'coffee-script' ); + +var App = require('./app'); +new App().start(); diff --git a/test/.gitkeep b/test/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/model/user-test.coffee b/test/model/user-test.coffee deleted file mode 100644 index 64e3ed5..0000000 --- a/test/model/user-test.coffee +++ /dev/null @@ -1,20 +0,0 @@ -chai = require 'chai' -expect = chai.expect - -User = require process.cwd() + '/src/models/user' - -chai.should() - - -describe 'User', -> - it 'email is set correct', -> - user = new User 'hans@mail.com' - user.email.should.equal 'hans@mail.com' - - it 'correct password allows login', -> - user = new User 'hans@mail.com' - user.login('p4ss').should.be.true - - it 'wrong password denies login', -> - user = new User 'hans@mail.com' - user.login('1234').should.be.false \ No newline at end of file diff --git a/views/.gitkeep b/views/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/views/error.jade b/views/404.jade similarity index 100% rename from views/error.jade rename to views/404.jade diff --git a/views/500.jade b/views/500.jade new file mode 100644 index 0000000..8b92627 --- /dev/null +++ b/views/500.jade @@ -0,0 +1,6 @@ +extends layout + +block content + h2 Ooops + p A #{error.code} error occured + pre #{error.message} \ No newline at end of file diff --git a/views/home.jade b/views/home.jade deleted file mode 100644 index 05f69df..0000000 --- a/views/home.jade +++ /dev/null @@ -1,3 +0,0 @@ -extends layout - -block content \ No newline at end of file diff --git a/views/home/index.jade b/views/home/index.jade new file mode 100644 index 0000000..e28e6c7 --- /dev/null +++ b/views/home/index.jade @@ -0,0 +1,3 @@ +extends ../layout + +block content \ No newline at end of file