spacedeck-open/routes/api/users.js

471 lines
14 KiB
JavaScript

"use strict";
var config = require('config');
require('../../models/schema');
var mailer = require('../../helpers/mailer');
var uploader = require('../../helpers/uploader');
var bcrypt = require('bcrypt');
var crypo = require('crypto');
var swig = require('swig');
var async = require('async');
var _ = require('underscore');
var fs = require('fs');
var request = require('request');
var gm = require('gm');
var validator = require('validator');
var express = require('express');
var router = express.Router();
router.get('/current', function(req, res, next) {
if (req.user) {
console.log(req.user.team);
res.status(200).json(req.user);
} else {
res.status(401).json({"error":"user_not_found"});
}
});
router.post('/', function(req, res) {
if (req.body["email"] && req.body["password"]) {
var email = req.body["email"].toLowerCase();
var nickname = req.body["nickname"];
var password = req.body["password"];
var password_confirmation = req.body["password_confirmation"];
if (password_confirmation == password) {
if (validator.isEmail(email)) {
var createUser = function() {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(password, salt, function(err, hash) {
crypo.randomBytes(16, function(ex, buf) {
var token = buf.toString('hex');
var u = new User({
email: email,
account_type: "email",
nickname: nickname,
password_hash: hash,
preferences: {
language: req.i18n.locale
},
confirmation_token: token
});
u.save(function (err) {
if (err) res.sendStatus(400);
else {
var homeSpace = new Space({
name: req.i18n.__("home"),
space_type: "folder",
creator: u
});
homeSpace.save((err, homeSpace) => {
if (err) res.sendStatus(400);
else {
u.home_folder_id = homeSpace._id;
u.save((err) => {
mailer.sendMail(u.email, req.i18n.__("confirm_subject"), req.i18n.__("confirm_body"), {
action: {
link: config.endpoint + "/confirm/" + u.confirmation_token,
name: req.i18n.__("confirm_action")
}
});
if (err) res.status(400).json(err);
else {
res.status(201).json({});
}
});
}
});
}
});
});
});
});
};
User.find({email: email}, (function (err, users) {
if (err) {
res.status(400).json({"error":"password_confirmation"});
} else {
if (users.length === 0) {
var domain = email.slice(email.lastIndexOf('@')+1);
Domain.findOne({domain: domain}, function(err, domain) {
if(domain){
if(domain.edu) {
createUser();
} else {
res.status(400).json({"error":"domain_blocked"});
}
} else {
createUser();
}
});
} else {
res.status(400).json({"error":"user_email_already_used"});
}
}
}));
} else {
res.status(400).json({"error":"email_invalid"});
}
} else {
res.status(400).json({"error":"password_confirmation"});
}
} else {
res.status(400).json({"error":"email or password missing"});
}
});
router.get('/oauth2callback/url', function(req, res) {
var google = require('googleapis');
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2(
config.google_access,
config.google_secret,
config.endpoint + "/login"
);
var url = oauth2Client.generateAuthUrl({
access_type: 'online',
scope: "email"
});
res.status(200).json({"url":url});
});
router.get('/loginorsignupviagoogle', function(req, res) {
var google = require('googleapis');
var OAuth2 = google.auth.OAuth2;
var plus = google.plus('v1');
var oauth2Client = new OAuth2(
config.google_access,
config.google_secret,
config.endpoint + "/login"
);
var loginUser = function(user, cb) {
crypo.randomBytes(48, function(ex, buf) {
var token = buf.toString('hex');
var session = {
token: token,
created_at: new Date()
};
if(!user.sessions)
user.sessions = [];
user.sessions.push(session);
user.save(function(err, user) {
cb(session);
});
});
};
var code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
if (err) res.status(400).json(err);
else {
var apiUrl = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=" + tokens.access_token;
var finalizeLogin = function(session){
var secure = process.env.NODE_ENV == "production" || process.env.NODE_ENV == "staging";
res.cookie('sdsession', session.token, { httpOnly: true, secure: secure});
res.status(201).json(session);
};
request.get(apiUrl, function(error, response, body) {
if (error) res.status(400).json(error);
else {
const data = JSON.parse(body);
const email = data.email;
const name = data.name;
User.findOne({email: email}, function (err, user) {
if (user) {
// login new google user
if (user.account_type == "google") {
// just login
loginUser(user, (session) => {
finalizeLogin(session);
});
} else {
res.status(400).json({"error":"user_email_already_used"});
}
} else {
const u = new User({
email: email,
account_type: "google",
nickname: name,
avatar_thumb_uri: body.picture,
preferences: {
language: req.i18n.locale
},
confirmed_at: new Date()
});
u.save(function (err) {
if (err) res.status(400).json(err);
else {
var homeSpace = new Space({
name: req.i18n.__("home"),
space_type: "folder",
creator: u
});
homeSpace.save(function(err, homeSpace) {
if (err) res.status(400).json(err);
else {
u.home_folder_id = homeSpace._id;
u.save(function(err){
if (err) res.sendStatus(400);
else {
mailer.sendMail(u.email, req.i18n.__("welcome_subject"), req.i18n.__("welcome_body"), {});
loginUser(u, function(session) {
finalizeLogin(session);
});
}
});
}
});
}
});
}
});
}
});
}
});
});
router.get('/ ', function(req, res, next) {
if (req.user) {
console.log(req.user.team);
res.status(200).json(req.user);
} else {
res.status(401).json({"error":"user_not_found"});
}
});
router.put('/:id', function(req, res, next) {
var user = req.user;
console.log(req.params.id, user._id);
if (user._id == req.params.id) {
var newAttr = req.body;
newAttr.updated_at = new Date();
delete newAttr['_id'];
User.findOneAndUpdate({"_id": user._id}, {"$set": newAttr}, function(err, updatedUser) {
if (err) {
res.sendStatus(400);
} else {
res.status(200).json(updatedUser);
}
});
} else {
res.sendStatus(403);
}
});
router.post('/:id/password', function(req, res, next) {
var user = req.user;
var old_password = req.body.old_password;
var pass = req.body.new_password;
if (pass.length >= 6) {
if (user._id == req.params.id) {
if (bcrypt.compareSync(old_password, user.password_hash)) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(pass, salt, function(err, hash) {
user.password_hash = hash;
user.save(function(err){
if(err){
res.status(400).json(err);
}else{
res.sendStatus(204);
}
});
});
});
} else {
res.status(403).json({"error": "old password wrong"});
}
} else {
res.status(403).json({"error": "wrong user"});
}
} else {
res.status(400).json({"error": "password_to_short"});
}
});
router.delete('/:id', (req, res, next) => {
const user = req.user;
if(user._id == req.params.id) {
if (user.account_type == 'email') {
if (bcrypt.compareSync(req.query.password, user.password_hash)) {
user.remove((err) => {
if(err)res.status(400).json(err);
else res.sendStatus(204);
});
} else {
res.bad_request("password_incorrect");
}
} else {
user.remove((err) => {
if(err)res.status(400).json(err);
else res.sendStatus(204);
});
}
}
else res.status(403).json({error: ""});
});
router.put('/:user_id/confirm', (req, res) => {
const token = req.body.token;
const user = req.user;
if (user.confirmation_token === token) {
user.confirmation_token = null;
user.confirmed_at = new Date();
user.save(function(err, updatedUser) {
if(err) {
res.sendStatus(400);
} else {
res.status(200).json(updatedUser);
}
});
} else {
res.sendStatus(400);
}
});
router.post('/:user_id/avatar', (req, res, next) => {
const user = req.user;
const filename = "u"+req.user._id+"_"+(new Date().getTime())+".jpeg"
const localFilePath = "/tmp/"+filename;
const localResizedFilePath = "/tmp/resized_"+filename;
const writeStream = fs.createWriteStream(localFilePath);
const stream = req.pipe(writeStream);
req.on('end', function() {
gm(localFilePath).resize(200, 200).autoOrient().write(localResizedFilePath, (err) => {
if (err) res.status(400).json(err);
else {
uploader.uploadFile(filename, "image/jpeg", localResizedFilePath, (err, url) => {
if (err) res.status(400).json(err);
else {
user.avatar_thumb_uri = url;
user.save((err, updatedUser) => {
if (err) {
res.sendStatus(400);
} else {
fs.unlink(localResizedFilePath, (err) => {
if (err) {
console.error(err);
res.status(400).json(err);
} else {
res.status(200).json(updatedUser);
}
});
}
});
}
});
}
});
});
});
router.post('/feedback', function(req, res, next) {
var text = req.body.text;
// FIXME
mailer.sendMail("support@example.org", "Support Request by " + req.user.email, text, {reply_to: req.user.email});
res.sendStatus(201);
});
router.post('/password_reset_requests', (req, res, next) => {
const email = req.query.email;
User.findOne({"email": email}).exec((err, user) => {
if (err) {
res.status(400).json(err);
} else {
if (user) {
if(user.account_type == "email") {
crypo.randomBytes(16, (ex, buf) => {
user.password_reset_token = buf.toString('hex');
user.save((err, updatedUser) => {
if (err) res.status(400).json(err);
else {
mailer.sendMail(email, req.i18n.__("password_reset_subject"), req.i18n.__("password_reset_body"), {action: {
link: config.endpoint + "/password-confirm/" + user.password_reset_token,
name: req.i18n.__("password_reset_action")
}});
res.status(201).json({});
}
});
});
} else {
res.status(404).json({"error": "error_unknown_email"});
}
} else {
res.status(404).json({"error": "error_unknown_email"});
}
}
});
});
router.post('/password_reset_requests/:confirm_token/confirm', function(req, res, next) {
var password = req.body.password;
User
.findOne({"password_reset_token": req.params.confirm_token})
.exec((err, user) => {
if (err) {
res.sendStatus(400);
} else {
if(user) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(password, salt, function(err, hash) {
user.password_hash = hash;
user.password_token = null;
user.save(function(err, updatedUser){
if (err) {
res.sendStatus(400);
} else {
res.sendStatus(201);
}
});
});
});
} else {
res.sendStatus(404);
}
}
});
});
router.post('/:user_id/confirm', function(req, res, next) {
mailer.sendMail(req.user.email, req.i18n.__("confirm_subject"), req.i18n.__("confirm_body"), { action:{
link: config.endpoint + "/confirm/" + req.user.confirmation_token,
name: req.i18n.__("confirm_action")
}});
res.sendStatus(201);
});
module.exports = router;