@ -1 +1,128 @@ |
|||||
# collectivecar |
|
||||
|
#ComunalCar app |
||||
|
|
||||
|
|
||||
|
**Backend:** |
||||
|
Nodejs + Express + MongoDB |
||||
|
|
||||
|
**Frontend:** |
||||
|
Angularjs + Materializecss |
||||
|
|
||||
|
|
||||
|
##Project Structure: |
||||
|
``` |
||||
|
comunalcar/ |
||||
|
server/ |
||||
|
controllers/ |
||||
|
userController.js |
||||
|
travelController.js |
||||
|
carController.js |
||||
|
askfortravelController.js |
||||
|
models/ |
||||
|
userModel.js |
||||
|
travelModel.js |
||||
|
carModel.js |
||||
|
needtravelModel.js |
||||
|
node_modules/ |
||||
|
config.js |
||||
|
server.js |
||||
|
package.js |
||||
|
README.md |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
##To Do List: |
||||
|
**Backend:** |
||||
|
``` |
||||
|
-signup user --> done |
||||
|
-loggin user --> done |
||||
|
-update user profile --> done |
||||
|
-create new travel --> done |
||||
|
-update travel --> done |
||||
|
-delete travel --> done |
||||
|
-create offeringCar |
||||
|
-update offeringCar |
||||
|
-delete offeringCar |
||||
|
-create askingForTravel (needtravel) |
||||
|
-update askingForTravel |
||||
|
-delete askgingForTravel |
||||
|
-user joins a car |
||||
|
-user joins travel |
||||
|
``` |
||||
|
|
||||
|
**Frontend:** |
||||
|
``` |
||||
|
-signup user |
||||
|
-loggin user |
||||
|
-update user profile |
||||
|
-create new travel |
||||
|
-update travel |
||||
|
-delete travel |
||||
|
-create offeringCar |
||||
|
-update offeringCar |
||||
|
-delete offeringCar |
||||
|
-create askingForTravel |
||||
|
-update askingForTravel |
||||
|
-delete askgingForTravel |
||||
|
``` |
||||
|
-------------------- |
||||
|
####**PARA LA BASE DE DATOS** [para definir como queremos q esté estructurado, pensando en las funcionalidades que queremos tener]: |
||||
|
|
||||
|
**user**: |
||||
|
-username |
||||
|
-password |
||||
|
-description |
||||
|
-icon/avatar |
||||
|
-mail |
||||
|
-phone |
||||
|
|
||||
|
**travel**: (seria cuando un user publica un nuevo trayecto que va a hacer) |
||||
|
-title |
||||
|
-description |
||||
|
-owner (user q ha publicado el viaje) |
||||
|
-from |
||||
|
-to |
||||
|
-date |
||||
|
-description |
||||
|
-generateddate (cuando el user genera el aviso) |
||||
|
-seats (plazas de coche disponibles) |
||||
|
|
||||
|
**car**: (cuando un user tiene un coche disponible para hacer viajes que se necesiten) |
||||
|
-title |
||||
|
-description |
||||
|
-owner (user q ha publicado el viaje) |
||||
|
-zone (la zona por la que está) |
||||
|
-available (cuando el user esta disponible, marca que esta disponible, si unos dias no podrá, lo desactiva) |
||||
|
-generateddate |
||||
|
-seats (plazas de coche disponibles) |
||||
|
|
||||
|
**needtravel**: (cuando un user no dispone de coche y necesita hacer un travel) |
||||
|
-title |
||||
|
-description |
||||
|
-owner (user q ha publicado el asking travel) |
||||
|
-from |
||||
|
-to |
||||
|
-date (las fechas para cuando se necesita el viaje) |
||||
|
-generateddate (cuando el user genera el aviso) |
||||
|
-seats (plazas de coche necesarias) |
||||
|
|
||||
|
**collectivizedCar**: (los coches/furgos comunales) --> quizás esto no hace falta, solo usar 'offeringCar' normal con un añadido para notificar que es un coche colectivizado |
||||
|
-owner (user q publica el coche) |
||||
|
-title |
||||
|
-seats (plazas de coche disponibles) |
||||
|
|
||||
|
-------------------- |
||||
|
|
||||
|
|
||||
|
|
||||
|
####**OTRAS COSAS**: |
||||
|
lo de poner o no un mapa, de entrada no destinaria esfuerzos en eso. Para la primera versión de la aplicación no hace falta, solo añade confort visual, para ver el recorrido, pero de entrada para una app q pone en contacto personas para compartir coche, no es algo imprescindible quizás |
||||
|
|
||||
|
|
||||
|
|
||||
|
####**RESOURCES to use**: |
||||
|
|
||||
|
car icons [http://www.flaticon.com/packs/transportation-7](http://www.flaticon.com/packs/transportation-7) |
||||
|
|
||||
|
css para la app: matterializeCSS [http://materializecss.com/](http://materializecss.com/) |
||||
|
|
||||
|
avatars users: [http://www.flaticon.com/packs/animal-icon-collection](http://www.flaticon.com/packs/animal-icon-collection) |
@ -0,0 +1,41 @@ |
|||||
|
# Logs |
||||
|
logs |
||||
|
*.log |
||||
|
npm-debug.log* |
||||
|
|
||||
|
# Runtime data |
||||
|
pids |
||||
|
*.pid |
||||
|
*.seed |
||||
|
*.pid.lock |
||||
|
|
||||
|
# Directory for instrumented libs generated by jscoverage/JSCover |
||||
|
lib-cov |
||||
|
|
||||
|
# Coverage directory used by tools like istanbul |
||||
|
coverage |
||||
|
|
||||
|
# nyc test coverage |
||||
|
.nyc_output |
||||
|
|
||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) |
||||
|
.grunt |
||||
|
|
||||
|
# node-waf configuration |
||||
|
.lock-wscript |
||||
|
|
||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html) |
||||
|
build/Release |
||||
|
|
||||
|
# Dependency directories |
||||
|
node_modules |
||||
|
jspm_packages |
||||
|
|
||||
|
# Optional npm cache directory |
||||
|
.npm |
||||
|
|
||||
|
# Optional eslint cache |
||||
|
.eslintcache |
||||
|
|
||||
|
# Optional REPL history |
||||
|
.node_repl_history |
@ -0,0 +1,7 @@ |
|||||
|
module.exports = { |
||||
|
|
||||
|
'secret': 'secretfortoken', |
||||
|
'database': 'mongodb://localhost/comunalcar', |
||||
|
"port" : process.env.PORT || 3000 |
||||
|
|
||||
|
}; |
@ -0,0 +1,97 @@ |
|||||
|
//File: controllers/travelController.js
|
||||
|
var mongoose = require('mongoose'); |
||||
|
var travelModel = mongoose.model('travelModel'); |
||||
|
|
||||
|
var userModel = mongoose.model('userModel'); |
||||
|
|
||||
|
//GET
|
||||
|
exports.findAllTravels = function(req, res) { |
||||
|
|
||||
|
travelModel.find(function(err, travels) { |
||||
|
if(err) res.send(500, err.message); |
||||
|
|
||||
|
res.status(200).jsonp(travels); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
//GET
|
||||
|
exports.findById = function(req, res) { |
||||
|
travelModel.findById(req.params.id, function(err, travel) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
|
||||
|
console.log('GET /travel/' + req.params.id); |
||||
|
res.status(200).jsonp(travel); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
exports.findAllTravelsFromUsername = function(req, res) { |
||||
|
travelModel.find({ |
||||
|
authorname: req.params.userid |
||||
|
}, function(err, travels) { |
||||
|
|
||||
|
if (err) throw err; |
||||
|
|
||||
|
if (!travels) { |
||||
|
res.json({ success: false, message: 'no travels for user' }); |
||||
|
} else if (travels) { |
||||
|
console.log(travels); |
||||
|
// return the information including token as JSON
|
||||
|
res.jsonp(travels); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
exports.addTravel = function(req, res) { |
||||
|
console.log('POST new travel, content: ' + req.body.content); |
||||
|
console.log(req.body); |
||||
|
|
||||
|
var travel = new travelModel({ |
||||
|
title: req.body.title, |
||||
|
description: req.body.description, |
||||
|
owner: req.body.owner, |
||||
|
from: req.body.from, |
||||
|
to: req.body.to, |
||||
|
date: req.body.date, |
||||
|
generateddate: req.body.generateddate, |
||||
|
seats: req.body.seats |
||||
|
}); |
||||
|
|
||||
|
travel.save(function(err, travel) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
res.status(200).jsonp(travel); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
//PUT
|
||||
|
exports.updateTravel = function(req, res) { |
||||
|
ActivityModel.findById(req.params.id, function(err, tvshow) { |
||||
|
tvshow.title = req.body.petId; |
||||
|
tvshow.year = req.body.year; |
||||
|
tvshow.country = req.body.country; |
||||
|
tvshow.poster = req.body.poster; |
||||
|
tvshow.seasons = req.body.seasons; |
||||
|
tvshow.genre = req.body.genre; |
||||
|
tvshow.summary = req.body.summary; |
||||
|
|
||||
|
tvshow.save(function(err) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
res.status(200).jsonp(tvshow); |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
//DELETE
|
||||
|
exports.deleteTravel = function(req, res) { |
||||
|
ActivityModel.findById(req.params.id, function(err, activity) { |
||||
|
activity.remove(function(err) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
res.status(200).jsonp(req.params.id); |
||||
|
console.log('DELETE /activities/' + req.params.id); |
||||
|
}) |
||||
|
}); |
||||
|
}; |
@ -0,0 +1,139 @@ |
|||||
|
//File: controllers/userController.js
|
||||
|
var mongoose = require('mongoose'); |
||||
|
var userModel = mongoose.model('userModel'); |
||||
|
|
||||
|
/* */ |
||||
|
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
|
||||
|
var express = require("express"); |
||||
|
var app = express(); |
||||
|
var config = require('../config'); // get our config file
|
||||
|
app.set('superSecret', config.secret); // secret variable
|
||||
|
/* */ |
||||
|
|
||||
|
//GET - Return all Users in the DB
|
||||
|
exports.findAllUsers = function(req, res) { |
||||
|
userModel.find(function(err, users) { |
||||
|
if(err) res.send(500, err.message); |
||||
|
|
||||
|
console.log('GET /users'); |
||||
|
res.status(200).jsonp(users); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
//GET - Return a User with specified ID
|
||||
|
exports.findById = function(req, res) { |
||||
|
userModel.findById(req.params.id, function(err, user) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
|
||||
|
console.log('GET /users/' + req.params.id); |
||||
|
res.status(200).jsonp(user); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
exports.findUserByUsername = function(req, res) { |
||||
|
userModel.find({ |
||||
|
username: req.params.username |
||||
|
}, function(err, user) { |
||||
|
|
||||
|
if (err) throw err; |
||||
|
|
||||
|
if (!user) { |
||||
|
res.json({ success: false, message: 'no user found' }); |
||||
|
} else if (user) { |
||||
|
console.log(user); |
||||
|
// return the information including token as JSON
|
||||
|
res.jsonp(user); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
//POST - Insert a new User in the DB
|
||||
|
exports.addUser = function(req, res) { |
||||
|
console.log('POST new user, name: ' + req.body.username); |
||||
|
//console.log(req.body);
|
||||
|
|
||||
|
var user = new userModel({ |
||||
|
username: req.body.username, |
||||
|
password: req.body.password, |
||||
|
description: req.body.description, |
||||
|
avatar: req.body.avatar, |
||||
|
mail: req.body.mail, |
||||
|
admin: req.body.admin |
||||
|
}); |
||||
|
|
||||
|
user.save(function(err, user) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
res.status(200).jsonp(user); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
//PUT - Update a user already exists
|
||||
|
exports.updateUser = function(req, res) { |
||||
|
userModel.findById(req.params.id, function(err, user) { |
||||
|
user.username = req.body.username; |
||||
|
user.password = req.body.password; |
||||
|
user.description = req.body.description; |
||||
|
user.avatar = req.body.avatar; |
||||
|
user.mail = req.body.mail; |
||||
|
user.admin = req.body.admin; |
||||
|
|
||||
|
user.save(function(err) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
res.status(200).jsonp(user); |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
//DELETE - Delete a user with specified ID
|
||||
|
exports.deleteUser = function(req, res) { |
||||
|
userModel.findById(req.params.id, function(err, user) { |
||||
|
user.remove(function(err) { |
||||
|
if(err) return res.send(500, err.message); |
||||
|
res.status(200).jsonp(req.params.id); |
||||
|
console.log('DELETE /users/' + req.params.id); |
||||
|
}) |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
//POST - auth user
|
||||
|
exports.login = function(req, res) { |
||||
|
// find the user
|
||||
|
userModel.findOne({ |
||||
|
username: req.body.username |
||||
|
}, function(err, user) { |
||||
|
|
||||
|
if (err) throw err; |
||||
|
|
||||
|
if (!user) { |
||||
|
res.json({ success: false, message: 'Authentication failed. User not found.' }); |
||||
|
} else if (user) { |
||||
|
|
||||
|
// check if password matches
|
||||
|
if (user.password != req.body.password) { |
||||
|
res.json({ success: false, message: 'Authentication failed. Wrong password.' }); |
||||
|
} else { |
||||
|
|
||||
|
// if user is found and password is right
|
||||
|
// create a token
|
||||
|
var token = jwt.sign(user, app.get('superSecret'), { |
||||
|
//expiresInMinutes: 1440 // expires in 24 hours
|
||||
|
expiresIn: '60m' |
||||
|
}); |
||||
|
console.log(user); |
||||
|
// return the information including token as JSON
|
||||
|
res.json({ |
||||
|
success: true, |
||||
|
message: 'Enjoy your token!', |
||||
|
token: token, |
||||
|
avatar: user.avatar |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
}; |
@ -0,0 +1,14 @@ |
|||||
|
var mongoose = require('mongoose'), |
||||
|
Schema = mongoose.Schema; |
||||
|
|
||||
|
|
||||
|
var carSchema = new Schema({ |
||||
|
title: { type: String }, |
||||
|
description: { type: String }, |
||||
|
owner: { type: String }, |
||||
|
zone: { type: String }, |
||||
|
available: { type: Boolean }, |
||||
|
generateddate: { type: Date }, |
||||
|
seats: { type: Number } |
||||
|
}) |
||||
|
module.exports = mongoose.model('carModel', carSchema); |
@ -0,0 +1,15 @@ |
|||||
|
var mongoose = require('mongoose'), |
||||
|
Schema = mongoose.Schema; |
||||
|
|
||||
|
|
||||
|
var needtravelSchema = new Schema({ |
||||
|
title: { type: String }, |
||||
|
description: { type: String }, |
||||
|
owner: { type: String }, |
||||
|
from: { type: String }, |
||||
|
to: { type: String }, |
||||
|
date: { type: Date }, |
||||
|
generateddate: { type: Date }, |
||||
|
seats: { type: Number } |
||||
|
}) |
||||
|
module.exports = mongoose.model('needtravelModel', needtravelSchema); |
@ -0,0 +1,15 @@ |
|||||
|
var mongoose = require('mongoose'), |
||||
|
Schema = mongoose.Schema; |
||||
|
|
||||
|
|
||||
|
var travelSchema = new Schema({ |
||||
|
title: { type: String }, |
||||
|
description: { type: String }, |
||||
|
owner: { type: String }, |
||||
|
from: { type: String }, |
||||
|
to: { type: String }, |
||||
|
date: { type: Date }, |
||||
|
generateddate: { type: Date }, |
||||
|
seats: { type: Number } |
||||
|
}) |
||||
|
module.exports = mongoose.model('travelModel', travelSchema); |
@ -0,0 +1,13 @@ |
|||||
|
var mongoose = require('mongoose'), |
||||
|
Schema = mongoose.Schema; |
||||
|
|
||||
|
|
||||
|
var userSchema = new Schema({ |
||||
|
username: { type: String }, |
||||
|
password: { type: String }, |
||||
|
description: { type: String }, |
||||
|
avatar: { type: String }, |
||||
|
mail: { type: String }, |
||||
|
phone: { type: String } |
||||
|
}) |
||||
|
module.exports = mongoose.model('userModel', userSchema); |
@ -0,0 +1,17 @@ |
|||||
|
{ |
||||
|
"name": "comunalCar", |
||||
|
"version": "0.0.1", |
||||
|
"description": "comunalCar, carsharing", |
||||
|
"main": "server.js", |
||||
|
"scripts": { |
||||
|
"start": "node server.js" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"mongoose": "^4.5.6", |
||||
|
"express": "^4.7.1", |
||||
|
"method-override": "^2.1.2", |
||||
|
"body-parser": "^1.5.1", |
||||
|
"jsonwebtoken" : "latest", |
||||
|
"morgan" : "latest" |
||||
|
} |
||||
|
} |
@ -0,0 +1,123 @@ |
|||||
|
var express = require("express"), |
||||
|
app = express(), |
||||
|
bodyParser = require("body-parser"), |
||||
|
methodOverride = require("method-override"), |
||||
|
mongoose = require('mongoose'); |
||||
|
|
||||
|
|
||||
|
var morgan = require('morgan'); |
||||
|
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
|
||||
|
var config = require('./config'); // get our config file
|
||||
|
|
||||
|
|
||||
|
// Connection to DB
|
||||
|
mongoose.connect(config.database, function(err, res) { |
||||
|
if(err) throw err; |
||||
|
console.log('Connected to Database'); |
||||
|
}); |
||||
|
app.set('superSecret', config.secret); // secret variable
|
||||
|
|
||||
|
// Middlewares
|
||||
|
app.use(bodyParser.urlencoded({ extended: false })); |
||||
|
app.use(bodyParser.json()); |
||||
|
app.use(methodOverride()); |
||||
|
|
||||
|
// use morgan to log requests to the console
|
||||
|
app.use(morgan('dev')); |
||||
|
|
||||
|
// Import Models and controllers
|
||||
|
var userMdl = require('./models/userModel')(app, mongoose); |
||||
|
var userCtrl = require('./controllers/userController'); |
||||
|
|
||||
|
var travelMdl = require('./models/travelModel')(app, mongoose); |
||||
|
var travelCtrl = require('./controllers/travelController'); |
||||
|
|
||||
|
/*// Example Route |
||||
|
var router = express.Router(); |
||||
|
router.get('/', function(req, res) { |
||||
|
res.send("Hello world!"); |
||||
|
}); |
||||
|
app.use(router);*/ |
||||
|
app.use(express.static(__dirname + '/web')); |
||||
|
|
||||
|
|
||||
|
//CORS
|
||||
|
app.use(function(req, res, next) { |
||||
|
res.header("Access-Control-Allow-Origin", "*"); |
||||
|
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); |
||||
|
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); |
||||
|
next(); |
||||
|
}); |
||||
|
|
||||
|
// API routes ------------------------------------------------------
|
||||
|
var apiRoutes = express.Router(); |
||||
|
|
||||
|
apiRoutes.route('/users') |
||||
|
.get(userCtrl.findAllUsers) |
||||
|
.post(userCtrl.addUser); |
||||
|
apiRoutes.route('/users/:id') |
||||
|
.get(userCtrl.findById); |
||||
|
apiRoutes.route('/users/byusername/:username') |
||||
|
.get(userCtrl.findUserByUsername); |
||||
|
apiRoutes.route('/travels/user/:userid') |
||||
|
.get(travelCtrl.findAllTravelsFromUsername); |
||||
|
|
||||
|
apiRoutes.route('/auth') |
||||
|
.post(userCtrl.login); |
||||
|
|
||||
|
apiRoutes.route('/travels') |
||||
|
.get(travelCtrl.findAllTravels); |
||||
|
|
||||
|
apiRoutes.route('/travels/:id') |
||||
|
.get(travelCtrl.findById) |
||||
|
|
||||
|
// route middleware to verify a token
|
||||
|
apiRoutes.use(function(req, res, next) { |
||||
|
|
||||
|
// check header or url parameters or post parameters for token
|
||||
|
var token = req.body.token || req.query.token || req.headers['x-access-token']; |
||||
|
|
||||
|
// decode token
|
||||
|
if (token) { |
||||
|
|
||||
|
// verifies secret and checks exp
|
||||
|
jwt.verify(token, app.get('superSecret'), function(err, decoded) { |
||||
|
if (err) { |
||||
|
return res.json({ success: false, message: 'Failed to authenticate token.' }); |
||||
|
} else { |
||||
|
// if everything is good, save to request for use in other routes
|
||||
|
req.decoded = decoded; |
||||
|
next(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
} else { |
||||
|
|
||||
|
// if there is no token
|
||||
|
// return an error
|
||||
|
return res.status(403).send({ |
||||
|
success: false, |
||||
|
message: 'No token provided.' |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
apiRoutes.route('/users/:id') |
||||
|
.put(userCtrl.updateUser) |
||||
|
.delete(userCtrl.deleteUser); |
||||
|
|
||||
|
apiRoutes.route('/travels') |
||||
|
.post(travelCtrl.addTravel); |
||||
|
|
||||
|
apiRoutes.route('/travels/:id') |
||||
|
.put(travelCtrl.updateTravel) |
||||
|
.delete(travelCtrl.deleteTravel); |
||||
|
|
||||
|
app.use('/api', apiRoutes); |
||||
|
// end of API routes -------------------------------------
|
||||
|
|
||||
|
// Start server
|
||||
|
app.listen(config.port, function() { |
||||
|
console.log("Node server running on http://localhost:3000"); |
||||
|
}); |