HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/RImmers2/portal.photomenu.nl/wwwroot/controllers/menus.js
exports.install = function () {
  F.route('/menus', menusIndex, ['get', 'authorize']);
  F.route('/menus/{restaurant}/{menu}/{type}', menusRestaurant, ['get', 'authorize']);
  F.route('/menus/{restaurant}/{menu}', menusRestaurant, ['get', 'authorize']);
  F.route('/menus/{restaurant}/{menu}/edit/{dish}', menusDish, ['get', 'authorize']);
  F.route('/menus/{restaurant}/{menu}/order/{direction}/{dish}', orderDish, ['get', 'authorize']);
  F.route('/menus/{restaurant}/{menu}/order/{direction}/{dish}', orderDish, ['get', 'authorize']);

  F.route('/menus/{restaurant}/{menu}/edit/{dish}', menusDishProcess, ['+xhr', 'upload', 'post', 'authorize']);
  F.route('/menus/{restaurant}/{menu}/delete/{dish}', menusDelete, ['get', 'authorize']);
};

const path = require('path');
const uuidV4 = require('uuid/v4');
const gm = require('gm').subClass({
  imageMagick: false
});

function sendEmail(fromaddress,toaddress,txtsubject,txthtml,bodytext,filePath) {
  var nodemailer = require('nodemailer');
  var smtpTransport = require('nodemailer-smtp-transport');
  var transporter = nodemailer.createTransport(smtpTransport({
   host: 'localhost',
   port: 25   
  }));
   transporter.sendMail({
   from: fromaddress,
   to: toaddress,
   subject: txtsubject,
   html: txthtml,
   text: bodytext,
//   attachments: [
//    {   // utf-8 string as an attachment
//       path: filePath
//    }]
  }).catch(err => {
        console.log(err);
  });
//  console.log('sendEmail successfull');
}

function menusIndex() {
  var self = this;
  var params = {};
  F.model('restaurant').list().then(function (snapshot) {
    params.list = [];
    if (self.repository.type === 'restaurant') {
      let data = snapshot.val()[self.repository.currentRestaurant];
      data.key = self.repository.currentRestaurant;
      params.list = [data];
    } else {
      snapshot.forEach(item => {
        let data = item.val();
        data.key = item.key;
        params.list.push(data);
      })
//      params.list = params.list.sort((i1, i2) => {
//        if (i1.Name.toLowerCase() < i2.Name.toLowerCase()) return -1;
//        if (i1.Name.toLowerCase() === i2.Name.toLowerCase()) return 0;
//        if (i1.Name.toLowerCase() > i2.Name.toLowerCase()) return 1;
//      });
	  params.list = params.list.sort((i1, i2) => i1.Inactive - i2.Inactive || i1.Name.toLowerCase().localeCompare(i2.Name.toLowerCase()));
    }
    self.layout('/layouts/protected');
    self.view('/menus/index', params);
  });
};

function menusRestaurant(restaurant, menu, type) {
  var self = this;
  var params = {};

  // Check if allowed access.
  if (self.repository.currentRestaurant && self.repository.currentRestaurant !== restaurant && self.repository.type !== 'admin') {
    self.res.redirect('/');
  }
  params.restaurantID = restaurant;
  params.menu = menu;
  params.type = type;

  const queryType = type === 'lunch' ? 'Lunch' : type;

  F.model('menu').loadDishes(menu, queryType).then(function (list) {
    let dishes = [];
    for (let id in list) {
      list[id].key = id;
      dishes.push(list[id]);
    }
    if (!type) {
      categories = {};

      categories.Starters = dishes.filter(d => d.Category === 'Starter').sort((d2, d1) => d2['Sort order'] - d1['Sort order']);
      categories['Side Dish'] = dishes.filter(d => d.Category === 'Side Dish').sort((d2, d1) => d2['Sort order'] - d1['Sort order']);
      categories['Main Dish'] = dishes.filter(d => d.Category === 'Main Dish').sort((d2, d1) => d2['Sort order'] - d1['Sort order']);
      categories.Dessert = dishes.filter(d => d.Category === 'Dessert').sort((d2, d1) => d2['Sort order'] - d1['Sort order']);
      categories.Menu = dishes.filter(d => d.Category === 'Menu').sort((d2, d1) => d2['Sort order'] - d1['Sort order']);
      categories.Drinks = dishes.filter(d => d.Category === 'Drinks').sort((d2, d1) => d2['Sort order'] - d1['Sort order']);
      params.list = categories;
    } else {
      params.list = dishes.sort((d2, d1) => d2['Sort order'] - d1['Sort order']);;

    }
    F.model('restaurant').load(restaurant).then(function (restaurant) {
      params.restaurant = restaurant;

      self.layout('/layouts/protected');
      self.view('/menus/dishes', params);
    });

  });
};


function orderDish(restaurant, menu, direction, dish) {
  var self = this;
  F.model('menu').loadDish(menu, dish).then(function (currentDishData) {
    F.model('menu').loadDishes(menu, currentDishData.Category).then(function (list) {
      let dishes = [];
      for (let id in list) {
        list[id].key = id;
        dishes.push(list[id]);
      }
      const sortedDishes = dishes.sort((d1, d2) => d2['Sort order'] - d1['Sort order']);
      const currentIndex = sortedDishes.findIndex(e => e.key === dish);
      const targetIndex = direction === 'down' ? currentIndex - 1 : currentIndex + 1;

      const targetOrderValue = sortedDishes[targetIndex]['Sort order'];
      sortedDishes[targetIndex]['Sort order'] = currentDishData['Sort order'];
      sortedDishes[currentIndex]['Sort order'] = targetOrderValue;

      const updateCurrent = F.model('menu').updateDish(menu, sortedDishes[currentIndex].key, sortedDishes[currentIndex]);
      const updateTarget = F.model('menu').updateDish(menu, sortedDishes[targetIndex].key, sortedDishes[targetIndex])
      Promise.all([updateCurrent, updateTarget]).then(() => {
        if (currentDishData.Category === 'Lunch')
          self.res.redirect(`/menus/${restaurant}/${menu}/lunch`);
        else {
          self.res.redirect(`/menus/${restaurant}/${menu}`);
        }
      }).catch(err => console.log(err))
    });
  });
}

function menusDish(restaurant, menu, dishID) {
  var self = this;
  var params = {
    dish: {},
    restaurantId: restaurant,
    menuId: menu,
    dishID: dishID,
	restauranthasStatistics: true
  };
    
  // Check if allowed access.
  if (self.repository.currentRestaurant && self.repository.currentRestaurant !== restaurant && self.repository.type !== 'admin') {
    self.res.redirect('/');
  }
  self.layout('/layouts/protected');
  if (dishID == 'new') {
    params.dish.Price = '€ ';
    self.view('/menus/edit', params);
  } else {
    F.model('menu').loadDish(menu, dishID).then(function (dish) {
      params.dish = dish;

      self.view('/menus/edit', params);
    });
  }

};

const validator = require('validator');

function menusDishProcess(restaurantID, menuID, dishID) {
  var self = this;
  let params = {
    dish: this.body,
    restaurantID: restaurantID,
    menuID: menuID,
    dishID: dishID,
    error: false
  };

  // Format data.
  params.dish['Inactive'] = self.body['Inactive'] == 'on' ? false : true;
  params.dish['Vegetarian'] = self.body['Vegetarian'] == 'on' ? true : false;

  params.dish['Allergen_gluten'] = self.body['Allergen_gluten'] == 'on' ? true : false;
  params.dish['Allergen_shellfish'] = self.body['Allergen_shellfish'] == 'on' ? true : false;
  params.dish['Allergen_eggs'] = self.body['Allergen_eggs'] == 'on' ? true : false;
  params.dish['Allergen_fish'] = self.body['Allergen_fish'] == 'on' ? true : false;
  params.dish['Allergen_peanut'] = self.body['Allergen_peanut'] == 'on' ? true : false;
  params.dish['Allergen_soya'] = self.body['Allergen_soya'] == 'on' ? true : false;
  params.dish['Allergen_milk'] = self.body['Allergen_milk'] == 'on' ? true : false;
  params.dish['Allergen_nuts'] = self.body['Allergen_nuts'] == 'on' ? true : false;
  params.dish['Allergen_celery'] = self.body['Allergen_celery'] == 'on' ? true : false;
  params.dish['Allergen_mustard'] = self.body['Allergen_mustard'] == 'on' ? true : false;
  params.dish['Allergen_sesame'] = self.body['Allergen_sesame'] == 'on' ? true : false;
  params.dish['Allergen_sulfur'] = self.body['Allergen_sulfur'] == 'on' ? true : false;
  params.dish['Allergen_lupine'] = self.body['Allergen_lupine'] == 'on' ? true : false;
  params.dish['Allergen_molluscs'] = self.body['Allergen_molluscs'] == 'on' ? true : false;

  params.dish['Category'] = self.body['Category'] === '---' ? null : self.body['Category'];

  if (!isNaN(parseInt(params.dish['Number of times shown in overview iOS']))) {
    params.dish['Number of times shown in overview iOS'] = parseInt(params.dish['Number of times shown in overview iOS']);
  }
  if (!isNaN(parseInt(params.dish['Number of times shown in overview android']))) {
    params.dish['Number of times shown in overview android'] = parseInt(params.dish['Number of times shown in overview android']);
  }
  if (!isNaN(parseInt(params.dish['Number of times shown in detail iOS']))) {
    params.dish['Number of times shown in detail iOS'] = parseInt(params.dish['Number of times shown in detail iOS']);
  }
  if (!isNaN(parseInt(params.dish['Number of times shown in detail android']))) {
    params.dish['Number of times shown in detail android'] = parseInt(params.dish['Number of times shown in detail android']);
  }
  if (!isNaN(parseInt(params.dish['Number of times shown in detail android']))) {
    params.dish['Number of times shown in detail android'] = parseInt(params.dish['Number of times shown in detail android']);
  }
  if (!isNaN(parseInt(params.dish['Sort order']))) {
    params.dish['Sort order'] = parseInt(params.dish['Sort order']);
  }
  const file = self.files[0];
  // Image validation.
  if (file) {
    // // Validate photo size and resolution.
    if (file.length > 10000000) {
      params.error = true;
      params.errorMessage = `"${file.filename}" is to large.`
    }
    const exp = new RegExp(/\.(gif|jpg|jpeg|png|GIF|JPG|JPEG|PNG)$/);
    if (!exp.test(file.filename)) {
      params.error = true;
      params.errorMessage = `"${file.filename}" is invalid type.`
    }
  } else {
    if (dishID === 'new') {
      params.error = true;
      params.errorMessage = `"Image" is required.`
    }
  }

  // Input validations.
//   if (!validator.isLength(self.body['Category'], {
//      min:0}
//	  )){
 
 
  if (!validator.isLength(self.body['Description'], {
      min: 0,
      max: 50
    })) {
    params.error = true;
    params.errorMessage = '"Description" value can have max 50 characters.';
  }
  if (!validator.isLength(self.body['Description ENG'], {
      min: 0,
      max: 50
    })) {
    params.error = true;
    params.errorMessage = '"Description ENG" value can have max 50 characters.'
  }
  if (!validator.isLength(self.body['Ingredients'], {
      min: 0,
      max: 100
    })) {
    params.error = true;
    params.errorMessage = '"Ingredients" value can have max 50 characters.'
  }
  if (!validator.isLength(self.body['Ingredients ENG'], {
      min: 0,
      max: 100
    })) {
    params.error = true;
    params.errorMessage = '"Ingredients ENG" value can have max 100 characters.'
  }
  if (!validator.isLength(self.body['Price'], {
      min: 1,
      max: 20
    })) {
    params.error = true;
    params.errorMessage = '"Price" value can have max 20 characters.'
    if (self.body['Price'].length < 1) {
      params.errorMessage = '"Price" value is required.'
    }
  }
  if (!validator.isLength(self.body['Title'], {
      min: 1,
      max: 25
    })) {
    params.error = true;
    params.errorMessage = '"Title" value can have max 20 characters.';
    if (self.body['Title'].length < 1) {
      params.errorMessage = '"Title" value is required.'
    }
  }
  if (!validator.isLength(self.body['Title ENG'], {
      min: 0,
      max: 25
    })) {
    params.error = true;
    params.errorMessage = '"Title ENG" value can have max 20 characters.'
  }
  if (self.body['Category']=== '-') {
    params.error = true;
    params.errorMessage = '"Category" is required.' 
  }

  if (params.error) {
    self.layout('/layouts/protected');
    F.model('menu').loadDish(menuID, dishID).then(function (old) {
      params.dish.Image = (old) ? old.Image : params.dish.Image;
      self.view('/menus/edit', params);
    });
  } else {
    if (file) {
      const options = {
        destination: `${params.restaurantID}/${uuidV4()}-${file.filename}`
      }
      let upload;
//      var strBody = 'Category: ' + params.dish.Category + ', Title: ' + params.dish.Title;
//	  sendEmail('info@photomenu.nl','photomenushares@gmail.com','New Image', strBody, strBody, null);
	  
	  if (file.length > 1000000 || file.width > 1500 || file.height > 1500) {
        upload = new Promise(function (resolve, reject) {
          const resizedPath = path.normalize(`${__dirname}/../tmp/${file.filename}`);
          gm(file.path).resize(1500, 1500).write(resizedPath, err => {
            if (err) {
              reject(err);
            }

            gm(file.path).thumb(1500, 0, resizedPath, 0, err => {
              F.storage.upload(resizedPath, options, function (err, uploaded, apiResponse) {
                if (err) {
                    return reject(err);
                }
                uploaded.makePublic(err => reject(err));
                params.dish.Image = uploaded.metadata.mediaLink;
                resolve(uploaded.metadata.mediaLink);
              })
            })
          });
        });

      } else {
        upload = new Promise(function (resolve, reject) {
          F.storage.upload(file.path, options, function (err, file, apiResponse) {
            if (err) {
                return reject(err);
            }
            file.makePublic(err => reject(err));
            params.dish.Image = file.metadata.mediaLink;
            resolve(file.metadata.mediaLink);
          })
        });
      }
      upload.then(() => {
// email new dish
       var user = F.firebaseAuth().currentUser;
        if (user.email!='info@photomenu.nl') {
     	  F.model('restaurant').load(restaurantID).then(function (restaurant) {
          var strMailBody = 'Restaurant: ' + restaurant.Name + '\nCategory: ' + params.dish.Category + '\nDishID: ' + dishID + '\nTitle: ' + params.dish.Title + '\nfilename: ' + file.filename + '\nfiletype: ' + file.type +'\nuser: ' + user.email;
		  var strHTMLMailBody = 'Restaurant: ' + restaurant.Name + '<br/>Category: ' + params.dish.Category + '<br/>DishID: ' + dishID + '<br/>Title: ' + params.dish.Title + '<br/>filename: ' + file.filename + '<br/>filetype: ' + file.type +'<br/>email: ' + user.email;
		  sendEmail('info@photomenu.nl','photomenushares@gmail.com','New/Edit Dish', strHTMLMailBody, strMailBody, null);
		  }).catch(err => console.log(err));
		}
// email new dish

		if (dishID === 'new') {          
		  F.model('menu').createDish(params.menuID, params.dish).then(function () {
            if (params.dish.Category === 'Lunch')
              self.res.redirect(`/menus/${restaurantID}/${menuID}/lunch`);
            else {
              self.res.redirect(`/menus/${restaurantID}/${menuID}`);
            }
          }).catch(err => {
            params.error = true;
            params.errorMessage = "Something went wrong while creating the dish. " + err;
			      sendEmail('info@photomenu.nl','photomenushares@gmail.com','Error while creating the dish.' , params.errorMessage, params.errorMessage,null);
            self.layout('/layouts/protected');
            self.view('/menus/edit', params);
          });
        } else {
		  F.model('menu').updateDish(params.menuID, params.dishID, params.dish).then(function () {
            if (params.dish.Category === 'Lunch')
              self.res.redirect(`/menus/${restaurantID}/${menuID}/lunch`);
            else {
              self.res.redirect(`/menus/${restaurantID}/${menuID}`);
            }
          }).catch(err => {
            params.error = true;
            params.errorMessage = "Something went wrong while updating the dish. " + err;
			sendEmail('info@photomenu.nl','photomenushares@gmail.com','Error while creating the dish.' , params.errorMessage, params.errorMessage,null);
            self.layout('/layouts/protected');
            self.view('/menus/edit', params);
          });
        }
      })
    } else {
      if (dishID === 'new') {
        F.model('menu').createDish(params.menuID, params.dish).then(function () {
          if (params.dish.Category === 'Lunch')
            self.res.redirect(`/menus/${restaurantID}/${menuID}/lunch`);
          else {
            self.res.redirect(`/menus/${restaurantID}/${menuID}`);
          }
        }).catch(err => {
          params.error = true;
          params.errorMessage = "Something went wrong while creating the dish. " + err;
		      sendEmail('info@photomenu.nl','photomenushares@gmail.com','Error while creating the dish.' , params.errorMessage, params.errorMessage,null);
          self.layout('/layouts/protected');
          self.view('/menus/edit', params);
        });
      } else {
        F.model('menu').updateDish(params.menuID, params.dishID, params.dish).then(function () {
          if (params.dish.Category === 'Lunch')
            self.res.redirect(`/menus/${restaurantID}/${menuID}/lunch`);
          else {
            self.res.redirect(`/menus/${restaurantID}/${menuID}`);
          }
        }).catch(err => {
          params.error = true;
          params.errorMessage = "Something went wrong while updating the dish."
		  sendEmail('info@photomenu.nl','photomenushares@gmail.com','Error while creating the dish.' , params.errorMessage, params.errorMessage,null);
          self.layout('/layouts/protected');
          self.view('/menus/edit', params);
        });
      }
    }
  }
};

function menusDelete(restaurantID, menuID, dishID) {
  var self = this;
  F.model('menu').loadDish(menuID, dishID).then(function (old) {
    F.model('menu').delete(menuID, dishID).then(function () {
      if (old.Category === 'Lunch')
        self.res.redirect(`/menus/${restaurantID}/${menuID}/lunch`);
      else {
        self.res.redirect(`/menus/${restaurantID}/${menuID}`);
      }
    });
  });
};