<commit_before>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// * This function highlights playlist elements

function highlight(i, which, persist) {
  $("tr:nth-child(" + i + ")").attr("id", "new-" + which);
  if (!persist) {
    $("tr." + which).removeClass(which);
  }
  $("#new-" + which).addClass(which);
  $("#new-" + which).removeAttr("id");
}

// * This function adds video elements to the playlist

function addVideoToList(name, time, spot, smooth) {
  name = escape(name);

  if (smooth) {
    smooth = " class=\"animated flipInX\"";
  }
  else {
    smooth = "";
  }

  //let trElement = "
" + name + "
<button class=\"tableButton removeButton\" onclick=\"buttonRemoveVideo(this);\" title=\"Remove\"></button>" +
  //"<button class=\"tableButton playButton\" onclick=\"buttonPlayVideo(this);\" title=\"Play\"></button>
	" + time + "
";

  let trElement = "
" + name +
  "
" +
  "" +
  "" +
  "" +
  "
	" + time + "
";

  if ($("#videosTable > tr").length > 0) {
    if (spot > 1) {
      $("#videosTable > tr").eq(spot-2).after(trElement);
    }
    else {
      $(trElement).insertBefore("#videosTable > tr:first");
    }
  }
  else {
    $("#videosTable").append(trElement);
  }
}

// * This function removes video elements from the playlist

function removeVideoFromList(index, smooth) {
  if (smooth === true) {
    $("tr:nth-child(" + index + ")").fadeOut(function() {
      $(this).remove();
    });
  }
  else {
    $("tr:nth-child(" + index + ")").remove();
  }
}

// * This function restores the video list highlighting as applicable
// * It does not use stored values, but rather the state of the playlist

function restoreHighlight(which) {
  if (which === videoIteration) {
    highlight(which, "selected", false);
  }
  if (videos[which][2] === baseAutoplayVideoId) {
    highlight(which, "radio", false);
  }
  if (videoErrorIds.indexOf(videos[which][2]) > -1) {
    highlight(which, "videoError", true);
  }
}

// * This function refreshes the playlist viewer with videos in the videos array
// * It's primary use is for playlist shuffling

function refreshVideoList() {
  for (let i = 1; i < videos.length; i++) {
    removeVideoFromList(i, false);
    let printTime = msConversion(videos[i][1] * 1000);
    addVideoToList(videos[i][0], printTime, i, false);
    restoreHighlight(i);
  }
}

// * These functions are called when the play/remove video buttons in the playlist viewer are clicked

let PlaylistButtons = function() {
  this.play = function(element) {
    let index = $(".playButton").index(element);
    actionPlayVideo(index);
  }
  this.remove = function(element) {
    let index = $(".removeButton").index(element) + 1;
    actionRemoveVideo(index);
  }
  this.autoplay = function(element) {
    let index = $(".autoplayButton").index(element) + 1;
    console.log("here: " + index);
    playlistAutoplay = true;
    addAutoplayVideo(index, 'reset');
    playlistFeatures.toggleSelected(playlistAutoplay, ".fa-rss");
  }
}
let playlistButtons = new PlaylistButtons;

// * This function makes the entire playlist viewer sortable by dragging&dropping
// * It calls the actionMoveVideo function above

function makeSortable() {
  $( "#videosTable" ).sortable({
    update: function(event, ui) {
      actionMoveVideo(oldIndex + 1, ui.item.index() + 1);
      setPlaylist();
      videoPreviews();
    },
    start: function(event, ui) {
      oldIndex = ui.item.index();
    },
    cancel: "span"
  });
}

// * This object is for the settings available in the playlist manipulation footer
// * Those buttons call their corresponding functionality here

let PlaylistFeatures = function() {
  let self = this;
  this.toggleSelected = function(doit, which) {
    if (doit) {
      $(which).addClass("selected");
    }
    else {
      $(which).removeClass("selected");
    }
  }
  this.playNext = function() {
    sendStation("playlistfeaturesplaynext");
    playlistPlayNext = (playlistPlayNext ? false : true);
    self.toggleSelected(playlistPlayNext, ".fa-arrow-circle-right");
  }
  this.repeat = function() {
    sendStation("playlistfeaturesrepeat");
    playlistRepeat = (playlistRepeat ? false : true);
    videoPreviews();
    self.toggleSelected(playlistRepeat, ".fa-redo-alt");
  }
  this.shuffle = function() {
    sendStation("playlistfeaturesshuffle");
    playlistShuffle = (playlistShuffle ? false : true);
    shufflePlaylist();
    self.toggleSelected(playlistShuffle, ".fa-random");
  }
  this.autoplay = function() {
    playlistAutoplay = (playlistAutoplay ? false : true);
    if (playlistAutoplay === false) {
      autoplayVideos = [];
      autoplayVideoIteration = 0;
      baseAutoplayVideoId = false;
      autoplayList = false;
      autoplayLoading = false;
      $("tr").removeClass("radio");
    }
    else {
      addAutoplayVideo();
    }
    self.toggleSelected(playlistAutoplay, ".fa-rss");
  }
}
let playlistFeatures = new PlaylistFeatures;

// * This function loads the previous and next video button's data in the playlist manipulation footer
// * It is called whenever anything changes in the playlist or the currently playing video changes

function videoPreviews() {
  if (!isMobile) {
    function addData(which, iteration) {
      $("#" + which + "Video .videoName").text(decodeURIComponent(videos[iteration][0]));
      $("#" + which + "Video .videoTime").text(msConversion(videos[iteration][1] * 1000));
      $("#" + which + "Video .videoImage").attr("src", "https://i.ytimg.com/vi/" + videos[iteration][2] + "/default.jpg");
    }
    function changeOpacity(which, amount) {
      $("#" + which + "Video .videoName, #" + which + "Video .videoImage, #" + which + "Video .videoTime").css("opacity", amount);
    }
    function greyOut(which, color) {
      $("#" + which + "Video").css("background-color", color);
      if (color === "white") {
        color = "black";
      }
      else {
        color = "inherit";
      }
      $("#" + which + "Video .videoImageContainer").css("background", color);
    }

    if (changeIteration(1) <= videoCounter) {
      changeOpacity("next", "1");
      greyOut("next", "white");
      addData("next", changeIteration(1));
    }
    else {
      changeOpacity("next", "0");
      greyOut("next", "grey");
    }

    if (changeIteration(-1) > 0 || (playlistRepeat && videoIteration == 1)) {
      changeOpacity("previous", "1");
      greyOut("previous", "white");
      addData("previous", (playlistRepeat && videoIteration == 1 ? changeIteration(-2) + 1 : changeIteration(-1)));
    }
    else {
      changeOpacity("previous", "0");
      greyOut("previous", "grey");
    }
  }
}
<commit_msg>use escape instead of decodeURI<commit_after>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// * This function highlights playlist elements

function highlight(i, which, persist) {
  $("tr:nth-child(" + i + ")").attr("id", "new-" + which);
  if (!persist) {
    $("tr." + which).removeClass(which);
  }
  $("#new-" + which).addClass(which);
  $("#new-" + which).removeAttr("id");
}

// * This function adds video elements to the playlist

function addVideoToList(name, time, spot, smooth) {
  name = escape(name);

  if (smooth) {
    smooth = " class=\"animated flipInX\"";
  }
  else {
    smooth = "";
  }

  //let trElement = "
" + name + "
<button class=\"tableButton removeButton\" onclick=\"buttonRemoveVideo(this);\" title=\"Remove\"></button>" +
  //"<button class=\"tableButton playButton\" onclick=\"buttonPlayVideo(this);\" title=\"Play\"></button>
	" + time + "
";

  let trElement = "
" + name +
  "
" +
  "" +
  "" +
  "" +
  "
	" + time + "
";

  if ($("#videosTable > tr").length > 0) {
    if (spot > 1) {
      $("#videosTable > tr").eq(spot-2).after(trElement);
    }
    else {
      $(trElement).insertBefore("#videosTable > tr:first");
    }
  }
  else {
    $("#videosTable").append(trElement);
  }
}

// * This function removes video elements from the playlist

function removeVideoFromList(index, smooth) {
  if (smooth === true) {
    $("tr:nth-child(" + index + ")").fadeOut(function() {
      $(this).remove();
    });
  }
  else {
    $("tr:nth-child(" + index + ")").remove();
  }
}

// * This function restores the video list highlighting as applicable
// * It does not use stored values, but rather the state of the playlist

function restoreHighlight(which) {
  if (which === videoIteration) {
    highlight(which, "selected", false);
  }
  if (videos[which][2] === baseAutoplayVideoId) {
    highlight(which, "radio", false);
  }
  if (videoErrorIds.indexOf(videos[which][2]) > -1) {
    highlight(which, "videoError", true);
  }
}

// * This function refreshes the playlist viewer with videos in the videos array
// * It's primary use is for playlist shuffling

function refreshVideoList() {
  for (let i = 1; i < videos.length; i++) {
    removeVideoFromList(i, false);
    let printTime = msConversion(videos[i][1] * 1000);
    addVideoToList(videos[i][0], printTime, i, false);
    restoreHighlight(i);
  }
}

// * These functions are called when the play/remove video buttons in the playlist viewer are clicked

let PlaylistButtons = function() {
  this.play = function(element) {
    let index = $(".playButton").index(element);
    actionPlayVideo(index);
  }
  this.remove = function(element) {
    let index = $(".removeButton").index(element) + 1;
    actionRemoveVideo(index);
  }
  this.autoplay = function(element) {
    let index = $(".autoplayButton").index(element) + 1;
    console.log("here: " + index);
    playlistAutoplay = true;
    addAutoplayVideo(index, 'reset');
    playlistFeatures.toggleSelected(playlistAutoplay, ".fa-rss");
  }
}
let playlistButtons = new PlaylistButtons;

// * This function makes the entire playlist viewer sortable by dragging&dropping
// * It calls the actionMoveVideo function above

function makeSortable() {
  $( "#videosTable" ).sortable({
    update: function(event, ui) {
      actionMoveVideo(oldIndex + 1, ui.item.index() + 1);
      setPlaylist();
      videoPreviews();
    },
    start: function(event, ui) {
      oldIndex = ui.item.index();
    },
    cancel: "span"
  });
}

// * This object is for the settings available in the playlist manipulation footer
// * Those buttons call their corresponding functionality here

let PlaylistFeatures = function() {
  let self = this;
  this.toggleSelected = function(doit, which) {
    if (doit) {
      $(which).addClass("selected");
    }
    else {
      $(which).removeClass("selected");
    }
  }
  this.playNext = function() {
    sendStation("playlistfeaturesplaynext");
    playlistPlayNext = (playlistPlayNext ? false : true);
    self.toggleSelected(playlistPlayNext, ".fa-arrow-circle-right");
  }
  this.repeat = function() {
    sendStation("playlistfeaturesrepeat");
    playlistRepeat = (playlistRepeat ? false : true);
    videoPreviews();
    self.toggleSelected(playlistRepeat, ".fa-redo-alt");
  }
  this.shuffle = function() {
    sendStation("playlistfeaturesshuffle");
    playlistShuffle = (playlistShuffle ? false : true);
    shufflePlaylist();
    self.toggleSelected(playlistShuffle, ".fa-random");
  }
  this.autoplay = function() {
    playlistAutoplay = (playlistAutoplay ? false : true);
    if (playlistAutoplay === false) {
      autoplayVideos = [];
      autoplayVideoIteration = 0;
      baseAutoplayVideoId = false;
      autoplayList = false;
      autoplayLoading = false;
      $("tr").removeClass("radio");
    }
    else {
      addAutoplayVideo();
    }
    self.toggleSelected(playlistAutoplay, ".fa-rss");
  }
}
let playlistFeatures = new PlaylistFeatures;

// * This function loads the previous and next video button's data in the playlist manipulation footer
// * It is called whenever anything changes in the playlist or the currently playing video changes

function videoPreviews() {
  if (!isMobile) {
    function addData(which, iteration) {
      $("#" + which + "Video .videoName").text(escape(videos[iteration][0]));
      $("#" + which + "Video .videoTime").text(msConversion(videos[iteration][1] * 1000));
      $("#" + which + "Video .videoImage").attr("src", "https://i.ytimg.com/vi/" + videos[iteration][2] + "/default.jpg");
    }
    function changeOpacity(which, amount) {
      $("#" + which + "Video .videoName, #" + which + "Video .videoImage, #" + which + "Video .videoTime").css("opacity", amount);
    }
    function greyOut(which, color) {
      $("#" + which + "Video").css("background-color", color);
      if (color === "white") {
        color = "black";
      }
      else {
        color = "inherit";
      }
      $("#" + which + "Video .videoImageContainer").css("background", color);
    }

    if (changeIteration(1) <= videoCounter) {
      changeOpacity("next", "1");
      greyOut("next", "white");
      addData("next", changeIteration(1));
    }
    else {
      changeOpacity("next", "0");
      greyOut("next", "grey");
    }

    if (changeIteration(-1) > 0 || (playlistRepeat && videoIteration == 1)) {
      changeOpacity("previous", "1");
      greyOut("previous", "white");
      addData("previous", (playlistRepeat && videoIteration == 1 ? changeIteration(-2) + 1 : changeIteration(-1)));
    }
    else {
      changeOpacity("previous", "0");
      greyOut("previous", "grey");
    }
  }
}
<|endoftext|>


<commit_before>/*
 * One Controller per layout view
 */

const fs = require('fs');
const pathUtils = require('path').posix;
const url = require('url');
const mime = require('mime');
const api = require('../api');
const rp = require('request-promise');
const express = require('express');
const router = express.Router();
const authHelper = require('../helpers/authentication');
const multer  = require('multer');
const upload = multer({ storage: multer.memoryStorage() });

const thumbs = {
    default: "/images/thumbs/default.png",
    psd: "/images/thumbs/psds.png",
    txt: "/images/thumbs/txts.png",
    doc: "/images/thumbs/docs.png",
    png: "/images/thumbs/pngs.png",
    mp4: "/images/thumbs/mp4s.png",
    mp3: "/images/thumbs/mp3s.png",
    aac: "/images/thumbs/aacs.png",
    avi: "/images/thumbs/avis.png",
    gif: "/images/thumbs/gifs.png",
    html: "/images/thumbs/htmls.png",
    js: "/images/thumbs/jss.png",
    mov: "/images/thumbs/movs.png",
    xls: "/images/thumbs/xlss.png",
    xlsx: "/images/thumbs/xlss.png",
    pdf: "/images/thumbs/pdfs.png",
    flac: "/images/thumbs/flacs.png",
    jpg: "/images/thumbs/jpgs.png",
    jpeg: "/images/thumbs/jpgs.png",
    docx: "/images/thumbs/docs.png",
    ai: "/images/thumbs/ais.png",
    tiff: "/images/thumbs/tiffs.png"
};

const requestSignedUrl = (req, data) => {
    return api(req).post('/fileStorage/signedUrl', {
        json: data
    });
};

const changeQueryParams = (originalUrl, params = {}, pathname = '') => {
    const urlParts = url.parse(originalUrl, true);

    Object.keys(params).forEach(param => {
        urlParts.query[param] = params[param];
    });

    if(pathname) {
        urlParts.pathname = pathname;
    }

    delete urlParts.search;
    return url.format(urlParts);
};

const getBreadcrumbs = (req, {dir = '', baseLabel = '', basePath = '/files/'} = {}) => {
    let dirParts = '';
    const currentDir = dir || req.query.dir || '';
    let pathComponents = currentDir.split('/') || [];
    if(pathComponents[0] === 'users' || pathComponents[0] === 'courses' || pathComponents[0] === 'classes') pathComponents = pathComponents.slice(2);   // remove context and ID, if present
    const breadcrumbs = pathComponents.filter(value => value).map(dirPart => {
        dirParts += '/' + dirPart;
        return {
            label: dirPart,
            url: changeQueryParams(req.originalUrl, {dir: dirParts}, basePath)
        };
    });

    if (baseLabel) {
        breadcrumbs.unshift({
            label: baseLabel,
            url: changeQueryParams(req.originalUrl, {dir: ''}, basePath)
        });
    }

    return breadcrumbs;
};

const getStorageContext = (req, res, options = {}) => {

    if (req.query.storageContext) {
        return pathUtils.normalize(req.query.storageContext + '/');
    }

    let currentDir = options.dir || req.query.dir || '/';
    const urlParts = url.parse((options.url || req.originalUrl), true);

    let storageContext = urlParts.pathname.replace('/files/', '/');

    if (storageContext === '/') {
        storageContext = 'users/' + res.locals.currentUser._id + '/';
    }

    if(currentDir.slice(-1) != '/') currentDir = currentDir + '/';
    return pathUtils.join(storageContext, currentDir);
};

const FileGetter = (req, res, next) => {
    let path = getStorageContext(req, res);
    let pathComponents = path.split('/');
    if(pathComponents[0] === '') pathComponents = pathComponents.slice(1); // remove leading slash, if present
    const currentDir = pathComponents.slice(2).join('/') || '/';

    path = pathComponents.join('/');

    return api(req).get('/fileStorage', {
        qs: {path}
    }).then(data => {
        let {files, directories} = data;

        files = files.map(file => {
            file.file = pathUtils.join(file.path, file.name);
            return file;
        });

        directories = directories.map(dir => {
            const targetUrl = pathUtils.join(currentDir, dir.name);
            dir.url = changeQueryParams(req.originalUrl, {dir: targetUrl});
            dir.path = pathUtils.join(path, dir.name);
            return dir;
        });

        res.locals.files = {
            files,
            directories,
            path
        };

        next();
    }).catch(err => {
        next(err);
    });
};

const getScopeDirs = (req, res, scope) => {
    return api(req).get('/' + scope + '/', {
        qs: {
            $or: [
                {userIds: res.locals.currentUser._id},
                {teacherIds: res.locals.currentUser._id}
            ]
        }
    }).then(records => {
        return records.data.map(record => {
            return Object.assign(record, {
                url: '/files/' + scope + '/' + record._id
            });
        });
    });
};

/**
 * register a new filePermission for the given user for the given file
 * @param userId {String} - the user which should be granted permission
 * @param filePath {String} - the file for which a new permission should be created
 */
const registerSharedPermission = (userId, filePath, req) => {
    // check whether a filePermission entry already exist for the given file
    return api(req).get('/filePermissions/', {qs: {key: filePath}}).then(res => {
        if (res.data.length <= 0) {
            // owner permits sharing of given file
            return Promise.reject("Zu dieser Datei haben Sie keinen Zugriff!");
        } else {
            let filePermission = res.data[0];
            filePermission.permissions.push({
                userId: userId,
                permissions: ['can-read', 'can-write'] // todo: make it selectable
            });
            return api(req).patch('/filePermissions/' + res.data[0]._id, {json: filePermission});
        }
    });
};

// secure routes
router.use(authHelper.authChecker);

const getSignedUrl = function (req, res, next) {
    let {type, path, action = 'putObject'} = req.body;
    path = path || req.query.path;
    const filename = (req.file || {}).originalname;
    if(filename) path = path + '/' + filename;

    const data = {
        path,
        fileType: (type || 'application/octet-stream'),
        action: action
    };

    return requestSignedUrl(req, data).then(signedUrl => {
       if(res) res.json({signedUrl, path});
        else return Promise.resolve({signedUrl, path});
    }).catch(err => {
        if(res) res.status((err.statusCode || 500)).send(err);
        else return Promise.reject(err);
    });
};

// get signed url to upload file
router.post('/file', getSignedUrl);

// upload file directly
router.post('/upload', upload.single('upload'), function (req, res, next) {
    let _path;
    return getSignedUrl(req, null, next).then(({signedUrl, path}) => {
        _path = path;
        return rp.put({
            url: signedUrl.url,
            headers: Object.assign({}, signedUrl.header, {
                'content-type': req.file.mimetype
            }),
            body: req.file.buffer
        });
    }).then(_ => {
        res.json({
            "uploaded": 1,
            "fileName": req.file.originalname,
            "url": "/files/file?path=" + _path
        });
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// delete file
router.delete('/file', function (req, res, next) {
    const {name, dir = ''} = req.body;
    const data = {
        path: dir + name,
        fileType: null,
        action: null
    };

    api(req).delete('/fileStorage/', {
        qs: data
    }).then(_ => {
        res.sendStatus(200);
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// get file
router.get('/file', function (req, res, next) {

    const {file, download = false, path, shared = false} = req.query;

    const basePath = getStorageContext(req, res, {url: req.get('Referrer')});
    const data = {
        path: path || basePath + file,
        fileType: mime.lookup(file || pathUtils.basename(path)),
        action: 'getObject'
    };

    let sharedPromise = shared ? registerSharedPermission(res.locals.currentUser._id, data.path, req) : Promise.resolve();
    sharedPromise.then(_ => {
        return requestSignedUrl(req, data).then(signedUrl => {
            return rp.get(signedUrl.url, {encoding: null}).then(awsFile => {
                if (download) {
                    res.type('application/octet-stream');
                    res.set('Content-Disposition', 'attachment;filename=' + pathUtils.basename(file));
                } else if (signedUrl.header['Content-Type']) {
                    res.type(signedUrl.header['Content-Type']);
                }

                res.end(awsFile, 'binary');
            });
        });
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// create directory
router.post('/directory', function (req, res, next) {
    const {name, dir} = req.body;

    const basePath = dir;
    const dirName = name || 'Neuer Ordner';
    api(req).post('/fileStorage/directories', {
        json: {
            path: basePath + dirName,
        }
    }).then(_ => {
        res.sendStatus(200);
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// delete directory
router.delete('/directory', function (req, res) {
    const data = {
        path: req.body.dir
    };

    api(req).delete('/fileStorage/directories/', {
        qs: data
    }).then(_ => {
        res.sendStatus(200);
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

router.get('/', FileGetter, function (req, res, next) {
    let files = res.locals.files.files;
    files.map(file => {
       let ending = file.name.split('.').pop();
       file.thumbnail = thumbs[ending] ? thumbs[ending] : thumbs['default'];
    });
    res.render('files/files', Object.assign({
        title: 'Dateien',
        path: res.locals.files.path,
        breadcrumbs: getBreadcrumbs(req, {
            baseLabel: 'Meine persönlichen Dateien'
        }),
        canUploadFile: true,
        canCreateDir: true,
        inline: req.query.inline || req.query.CKEditor,
        CKEditor: req.query.CKEditor
    }, res.locals.files));
});

router.get('/courses/', function (req, res, next) {
    const basePath = '/files/courses/';
    getScopeDirs(req, res, 'courses').then(directories => {
        const breadcrumbs = getBreadcrumbs(req, {basePath});

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Fächern und Kursen',
            url: changeQueryParams(req.originalUrl, {dir: ''}, '/files/courses/')
        });

        res.render('files/files', {
            title: 'Dateien',
            path: getStorageContext(req, res),
            breadcrumbs,
            files: [],
            directories
        });
    });
});

router.get('/courses/:courseId', FileGetter, function (req, res, next) {
    const basePath = '/files/courses/';
    api(req).get('/courses/' + req.params.courseId).then(record => {
        let files = res.locals.files.files;
        files.map(file => {
            let ending = file.name.split('.').pop();
            file.thumbnail = thumbs[ending] ? thumbs[ending] : thumbs['default'];
        });

        const breadcrumbs = getBreadcrumbs(req, {basePath: basePath + record._id});

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Fächern und Kursen',
            url: req.query.CKEditor ? '#' : changeQueryParams(req.originalUrl, {dir: ''}, basePath)
        }, {
            label: record.name,
            url: changeQueryParams(req.originalUrl, {dir: ''}, basePath + record._id)
        });

        res.render('files/files', Object.assign({
            title: 'Dateien',
            canUploadFile: true,
            canCreateDir: true,
            path: res.locals.files.path,
            inline: req.query.inline || req.query.CKEditor,
            CKEditor: req.query.CKEditor,
            breadcrumbs,
            courseId: req.params.courseId,
            courseUrl: `/courses/${req.params.courseId}/`
        }, res.locals.files));

    });
});

router.get('/classes/', function (req, res, next) {
    getScopeDirs(req, res, 'classes').then(directories => {
        const breadcrumbs = getBreadcrumbs(req);

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Klassen',
            url: changeQueryParams(req.originalUrl, {dir: ''}, '/files/classes/')
        });

        res.render('files/files', {
            title: 'Dateien',
            path: getStorageContext(req, res),
            breadcrumbs,
            files: [],
            directories
        });
    });
});

router.get('/classes/:classId', FileGetter, function (req, res, next) {
    const basePath = '/files/classes/';
    api(req).get('/classes/' + req.params.classId).then(record => {
        let files = res.locals.files.files;
        files.map(file => {
            let ending = file.name.split('.').pop();
            file.thumbnail = thumbs[ending] ? thumbs[ending] : thumbs['default'];
        });

        const breadcrumbs = getBreadcrumbs(req, {basePath});

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Klassen',
            url: req.query.CKEditor ? '#' : changeQueryParams(req.originalUrl, {dir: ''}, basePath)
        }, {
            label: record.name,
            url: changeQueryParams(req.originalUrl, {dir: ''}, basePath + record._id)
        });

        res.render('files/files', Object.assign({
            title: 'Dateien',
            path: res.locals.files.path,
            canUploadFile: true,
            breadcrumbs,
            inline: req.query.inline || req.query.CKEditor,
            CKEditor: req.query.CKEditor,
        }, res.locals.files));

    });
});

router.post('/permissions/', function (req, res, next) {
    // todo: refactoring sharing!
    api(req).get('/files/', { qs: {key: req.body.key} }).then(filePermission => {
        if (filePermission.data.length > 0) {
            res.json(filePermission.data[0]);
        } else {
            api(req).post("/files/", { json: req.body }).then(filePermission => {
                res.json(filePermission);
            });
        }
    });
});

/**** File and Directory proxy models ****/
router.post('/fileModel', function (req, res, next) {
    api(req).post('/files/', { json: req.body }).then(file => res.json(file)).catch(err => next(err));
});

module.exports = router;
<commit_msg>refactor file open<commit_after>/*
 * One Controller per layout view
 */

const fs = require('fs');
const pathUtils = require('path').posix;
const url = require('url');
const mime = require('mime');
const api = require('../api');
const rp = require('request-promise');
const express = require('express');
const router = express.Router();
const authHelper = require('../helpers/authentication');
const multer  = require('multer');
const upload = multer({ storage: multer.memoryStorage() });

const thumbs = {
    default: "/images/thumbs/default.png",
    psd: "/images/thumbs/psds.png",
    txt: "/images/thumbs/txts.png",
    doc: "/images/thumbs/docs.png",
    png: "/images/thumbs/pngs.png",
    mp4: "/images/thumbs/mp4s.png",
    mp3: "/images/thumbs/mp3s.png",
    aac: "/images/thumbs/aacs.png",
    avi: "/images/thumbs/avis.png",
    gif: "/images/thumbs/gifs.png",
    html: "/images/thumbs/htmls.png",
    js: "/images/thumbs/jss.png",
    mov: "/images/thumbs/movs.png",
    xls: "/images/thumbs/xlss.png",
    xlsx: "/images/thumbs/xlss.png",
    pdf: "/images/thumbs/pdfs.png",
    flac: "/images/thumbs/flacs.png",
    jpg: "/images/thumbs/jpgs.png",
    jpeg: "/images/thumbs/jpgs.png",
    docx: "/images/thumbs/docs.png",
    ai: "/images/thumbs/ais.png",
    tiff: "/images/thumbs/tiffs.png"
};

const requestSignedUrl = (req, data) => {
    return api(req).post('/fileStorage/signedUrl', {
        json: data
    });
};

const changeQueryParams = (originalUrl, params = {}, pathname = '') => {
    const urlParts = url.parse(originalUrl, true);

    Object.keys(params).forEach(param => {
        urlParts.query[param] = params[param];
    });

    if(pathname) {
        urlParts.pathname = pathname;
    }

    delete urlParts.search;
    return url.format(urlParts);
};

const getBreadcrumbs = (req, {dir = '', baseLabel = '', basePath = '/files/'} = {}) => {
    let dirParts = '';
    const currentDir = dir || req.query.dir || '';
    let pathComponents = currentDir.split('/') || [];
    if(pathComponents[0] === 'users' || pathComponents[0] === 'courses' || pathComponents[0] === 'classes') pathComponents = pathComponents.slice(2);   // remove context and ID, if present
    const breadcrumbs = pathComponents.filter(value => value).map(dirPart => {
        dirParts += '/' + dirPart;
        return {
            label: dirPart,
            url: changeQueryParams(req.originalUrl, {dir: dirParts}, basePath)
        };
    });

    if (baseLabel) {
        breadcrumbs.unshift({
            label: baseLabel,
            url: changeQueryParams(req.originalUrl, {dir: ''}, basePath)
        });
    }

    return breadcrumbs;
};

const getStorageContext = (req, res, options = {}) => {

    if (req.query.storageContext) {
        return pathUtils.normalize(req.query.storageContext + '/');
    }

    let currentDir = options.dir || req.query.dir || '/';
    const urlParts = url.parse((options.url || req.originalUrl), true);

    let storageContext = urlParts.pathname.replace('/files/', '/');

    if (storageContext === '/') {
        storageContext = 'users/' + res.locals.currentUser._id + '/';
    }

    if(currentDir.slice(-1) != '/') currentDir = currentDir + '/';
    return pathUtils.join(storageContext, currentDir);
};

const FileGetter = (req, res, next) => {
    let path = getStorageContext(req, res);
    let pathComponents = path.split('/');
    if(pathComponents[0] === '') pathComponents = pathComponents.slice(1); // remove leading slash, if present
    const currentDir = pathComponents.slice(2).join('/') || '/';

    path = pathComponents.join('/');

    return api(req).get('/fileStorage', {
        qs: {path}
    }).then(data => {
        let {files, directories} = data;

        files = files.map(file => {
            file.file = pathUtils.join(file.path, file.name);
            return file;
        });

        directories = directories.map(dir => {
            const targetUrl = pathUtils.join(currentDir, dir.name);
            dir.url = changeQueryParams(req.originalUrl, {dir: targetUrl});
            dir.path = pathUtils.join(path, dir.name);
            return dir;
        });

        res.locals.files = {
            files,
            directories,
            path
        };

        next();
    }).catch(err => {
        next(err);
    });
};

const getScopeDirs = (req, res, scope) => {
    return api(req).get('/' + scope + '/', {
        qs: {
            $or: [
                {userIds: res.locals.currentUser._id},
                {teacherIds: res.locals.currentUser._id}
            ]
        }
    }).then(records => {
        return records.data.map(record => {
            return Object.assign(record, {
                url: '/files/' + scope + '/' + record._id
            });
        });
    });
};

/**
 * register a new filePermission for the given user for the given file
 * @param userId {String} - the user which should be granted permission
 * @param filePath {String} - the file for which a new permission should be created
 */
const registerSharedPermission = (userId, filePath, req) => {
    // check whether a filePermission entry already exist for the given file
    return api(req).get('/filePermissions/', {qs: {key: filePath}}).then(res => {
        if (res.data.length <= 0) {
            // owner permits sharing of given file
            return Promise.reject("Zu dieser Datei haben Sie keinen Zugriff!");
        } else {
            let filePermission = res.data[0];
            filePermission.permissions.push({
                userId: userId,
                permissions: ['can-read', 'can-write'] // todo: make it selectable
            });
            return api(req).patch('/filePermissions/' + res.data[0]._id, {json: filePermission});
        }
    });
};

// secure routes
router.use(authHelper.authChecker);

const getSignedUrl = function (req, res, next) {
    let {type, path, action = 'putObject'} = req.body;
    path = path || req.query.path;
    const filename = (req.file || {}).originalname;
    if(filename) path = path + '/' + filename;

    const data = {
        path,
        fileType: (type || 'application/octet-stream'),
        action: action
    };

    return requestSignedUrl(req, data).then(signedUrl => {
       if(res) res.json({signedUrl, path});
        else return Promise.resolve({signedUrl, path});
    }).catch(err => {
        if(res) res.status((err.statusCode || 500)).send(err);
        else return Promise.reject(err);
    });
};

// get signed url to upload file
router.post('/file', getSignedUrl);

// upload file directly
router.post('/upload', upload.single('upload'), function (req, res, next) {
    let _path;
    return getSignedUrl(req, null, next).then(({signedUrl, path}) => {
        _path = path;
        return rp.put({
            url: signedUrl.url,
            headers: Object.assign({}, signedUrl.header, {
                'content-type': req.file.mimetype
            }),
            body: req.file.buffer
        });
    }).then(_ => {
        res.json({
            "uploaded": 1,
            "fileName": req.file.originalname,
            "url": "/files/file?path=" + _path
        });
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// delete file
router.delete('/file', function (req, res, next) {
    const {name, dir = ''} = req.body;
    const data = {
        path: dir + name,
        fileType: null,
        action: null
    };

    api(req).delete('/fileStorage/', {
        qs: data
    }).then(_ => {
        res.sendStatus(200);
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// get file
router.get('/file', function (req, res, next) {

    const {file, download = false, path, shared = false} = req.query;
    const data = {
        path: path || file,
        fileType: mime.lookup(file || pathUtils.basename(path)),
        action: 'getObject'
    };

    let sharedPromise = shared ? registerSharedPermission(res.locals.currentUser._id, data.path, req) : Promise.resolve();
    sharedPromise.then(_ => {
        return requestSignedUrl(req, data).then(signedUrl => {
            return rp.get(signedUrl.url, {encoding: null}).then(awsFile => {
                if (download) {
                    res.type('application/octet-stream');
                    res.set('Content-Disposition', 'attachment;filename=' + pathUtils.basename(file));
                } else if (signedUrl.header['Content-Type']) {
                    res.type(signedUrl.header['Content-Type']);
                }

                res.end(awsFile, 'binary');
            });
        });
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// create directory
router.post('/directory', function (req, res, next) {
    const {name, dir} = req.body;

    const basePath = dir;
    const dirName = name || 'Neuer Ordner';
    api(req).post('/fileStorage/directories', {
        json: {
            path: basePath + dirName,
        }
    }).then(_ => {
        res.sendStatus(200);
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

// delete directory
router.delete('/directory', function (req, res) {
    const data = {
        path: req.body.dir
    };

    api(req).delete('/fileStorage/directories/', {
        qs: data
    }).then(_ => {
        res.sendStatus(200);
    }).catch(err => {
        res.status((err.statusCode || 500)).send(err);
    });
});

router.get('/', FileGetter, function (req, res, next) {
    let files = res.locals.files.files;
    files.map(file => {
       let ending = file.name.split('.').pop();
       file.thumbnail = thumbs[ending] ? thumbs[ending] : thumbs['default'];
    });
    res.render('files/files', Object.assign({
        title: 'Dateien',
        path: res.locals.files.path,
        breadcrumbs: getBreadcrumbs(req, {
            baseLabel: 'Meine persönlichen Dateien'
        }),
        canUploadFile: true,
        canCreateDir: true,
        inline: req.query.inline || req.query.CKEditor,
        CKEditor: req.query.CKEditor
    }, res.locals.files));
});

router.get('/courses/', function (req, res, next) {
    const basePath = '/files/courses/';
    getScopeDirs(req, res, 'courses').then(directories => {
        const breadcrumbs = getBreadcrumbs(req, {basePath});

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Fächern und Kursen',
            url: changeQueryParams(req.originalUrl, {dir: ''}, '/files/courses/')
        });

        res.render('files/files', {
            title: 'Dateien',
            path: getStorageContext(req, res),
            breadcrumbs,
            files: [],
            directories
        });
    });
});

router.get('/courses/:courseId', FileGetter, function (req, res, next) {
    const basePath = '/files/courses/';
    api(req).get('/courses/' + req.params.courseId).then(record => {
        let files = res.locals.files.files;
        files.map(file => {
            let ending = file.name.split('.').pop();
            file.thumbnail = thumbs[ending] ? thumbs[ending] : thumbs['default'];
        });

        const breadcrumbs = getBreadcrumbs(req, {basePath: basePath + record._id});

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Fächern und Kursen',
            url: req.query.CKEditor ? '#' : changeQueryParams(req.originalUrl, {dir: ''}, basePath)
        }, {
            label: record.name,
            url: changeQueryParams(req.originalUrl, {dir: ''}, basePath + record._id)
        });

        res.render('files/files', Object.assign({
            title: 'Dateien',
            canUploadFile: true,
            canCreateDir: true,
            path: res.locals.files.path,
            inline: req.query.inline || req.query.CKEditor,
            CKEditor: req.query.CKEditor,
            breadcrumbs,
            courseId: req.params.courseId,
            courseUrl: `/courses/${req.params.courseId}/`
        }, res.locals.files));

    });
});

router.get('/classes/', function (req, res, next) {
    getScopeDirs(req, res, 'classes').then(directories => {
        const breadcrumbs = getBreadcrumbs(req);

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Klassen',
            url: changeQueryParams(req.originalUrl, {dir: ''}, '/files/classes/')
        });

        res.render('files/files', {
            title: 'Dateien',
            path: getStorageContext(req, res),
            breadcrumbs,
            files: [],
            directories
        });
    });
});

router.get('/classes/:classId', FileGetter, function (req, res, next) {
    const basePath = '/files/classes/';
    api(req).get('/classes/' + req.params.classId).then(record => {
        let files = res.locals.files.files;
        files.map(file => {
            let ending = file.name.split('.').pop();
            file.thumbnail = thumbs[ending] ? thumbs[ending] : thumbs['default'];
        });

        const breadcrumbs = getBreadcrumbs(req, {basePath});

        breadcrumbs.unshift({
            label: 'Dateien aus meinen Klassen',
            url: req.query.CKEditor ? '#' : changeQueryParams(req.originalUrl, {dir: ''}, basePath)
        }, {
            label: record.name,
            url: changeQueryParams(req.originalUrl, {dir: ''}, basePath + record._id)
        });

        res.render('files/files', Object.assign({
            title: 'Dateien',
            path: res.locals.files.path,
            canUploadFile: true,
            breadcrumbs,
            inline: req.query.inline || req.query.CKEditor,
            CKEditor: req.query.CKEditor,
        }, res.locals.files));

    });
});

router.post('/permissions/', function (req, res, next) {
    // todo: refactoring sharing!
    api(req).get('/files/', { qs: {key: req.body.key} }).then(filePermission => {
        if (filePermission.data.length > 0) {
            res.json(filePermission.data[0]);
        } else {
            api(req).post("/files/", { json: req.body }).then(filePermission => {
                res.json(filePermission);
            });
        }
    });
});

/**** File and Directory proxy models ****/
router.post('/fileModel', function (req, res, next) {
    api(req).post('/files/', { json: req.body }).then(file => res.json(file)).catch(err => next(err));
});

module.exports = router;
<|endoftext|>


<commit_before>$(document).ready(function() {
    function NavBarModel() {
        var self = this;
        self.filters = ko.observableArray();
    };

    var nbm = new NavBarModel();
    ko.applyBindings(nbm);

    /* TODO: Figure out how to stuff filters into a
       computed observable so this function gets called
       on filter updates. Possibly using HTTP long-polling
     */

    // FIXME: Add some filters, change this to /filters/, .filters
    $.getJSON('/api/clusters/', function(data) {
        nbm.filters(data.clusters);
        // Activate first navbar item
        $('.navbar * ul.nav li').first().addClass('active');
    });

    // Activate first nav-list item
    $('ul.nav-list li a').parent().first().addClass('active');
});
<commit_msg>Change to filters now that can-has prebaked<commit_after>$(document).ready(function() {
    function NavBarModel() {
        var self = this;
        self.filters = ko.observableArray();
    };

    var nbm = new NavBarModel();
    ko.applyBindings(nbm);

    /* TODO: Figure out how to stuff filters into a
       computed observable so this function gets called
       on filter updates. Possibly using HTTP long-polling
     */

    $.getJSON('/api/filters/', function(data) {
        nbm.filters(data.filters);
        // Activate first navbar item
        $('.navbar * ul.nav li').first().addClass('active');
    });

    // Activate first nav-list item
    $('ul.nav-list li a').parent().first().addClass('active');
});
<|endoftext|>


<commit_before>var http = require('http');
var MealPlan = require('./mealPlanModel');

var saveMealPlan = function(recipes){
  var recipeIds = [];
  for (var i = 0; i < recipes.length; i++) {
    recipeIds.push(recipes[i].id);
  }

  new MealPlan({
    'userId': 0
  }).save().then(function(mealPlan){
    return mealPlan.recipes().attach(recipeIds);
  }).catch(function(error) {
    console.error("On associating recipes with meal plan got error:", error);
  });
};

module.exports = {
  createMealPlan: function (request, response) {
    saveMealPlan(request.body.recipes);
    response.status(200).send({});
  },
};
<commit_msg>Meal plans now saved with userId<commit_after>var http = require('http');
var MealPlan = require('./mealPlanModel');

var saveMealPlan = function(requestBody){
  var recipeIds = [];
  for (var i = 0; i < requestBody.recipes.length; i++) {
    recipeIds.push(requestBody.recipes[i].id);
  }

  var userId = requestBody.userId || 0;
  new MealPlan({
    'userId': userId
  }).save().then(function(mealPlan){
    return mealPlan.recipes().attach(recipeIds);
  }).catch(function(error) {
    console.error("On associating recipes with meal plan got error:", error);
  });
};

module.exports = {
  createMealPlan: function (request, response) {
    saveMealPlan(request.body);
    response.status(200).send({});
  },
};
<|endoftext|>


<commit_before>var path = require('path');
var webpack = require('webpack');
var defaults = require('./defaults');
var browserStackBrowsers = require('./browserstack.browsers');

var defaultsPlugin = new webpack.DefinePlugin(defaults);

var allBrowsers = browserStackBrowsers.filter('bs_all');
var allBrowsersByBrowser = {};
allBrowsers.forEach(function(browser) {
  allBrowsersByBrowser[browser._alias] = browser;
});

module.exports = function (config) {
  config.set({
    browsers: ['PhantomJS'],

    // The Travis environment has these specified.
    // To run BrowserStack tests locally, specify the environment variables:
    //  BROWSER_STACK_USERNAME, BROWSER_STACK_ACCESS_KEY
    browserStack: {
      username: null,
      accessKey: null
    },

    client: {
      captureConsole: true
    },

    // Used for testing on BrowserStack
    customLaunchers: allBrowsersByBrowser,

    // Files are specified in the grunt-karma configuration in Gruntfile.js
    //files: []

    frameworks: ['mocha', 'expect', 'sinon', 'jquery-1.9.0'],

    logLevel: 'INFO',

    // Default is 1000 but we can run into rate limit issues so bump it up to 10k
    pollingTimeout: 10000,

    // run the bundle through the webpack and sourcemap plugins
    preprocessors: {
      /*
      'test-browser/!(requirejs).test.js': ['webpack']
      */
      'test/!(requirejs).test.js': ['webpack'],
      'src/**/*.js': ['coverage']
    },

    proxies: {
      '/dist/rollbar.js': '/base/dist/rollbar.js'
    },

    reporters: ['progress', 'coverage'],

    singleRun: true,

    // Use "polling" and JSONP for older browsers
    transports: ['polling'],
    forceJSONP: true,

    webpack: {
      eslint: {
        configFile: path.resolve(__dirname, ".eslintrc")
      },
      plugins: [defaultsPlugin],
      module: {
        preLoaders: [
          {
            test: /\.js$/,
            loader: "strict!eslint",
            exclude: [/node_modules/, /vendor/, /lib/, /dist/]
          }
        ],
        loaders: [
          {
            test: /(mootootls|requirejs)\.js$/,
            loader: 'script'
          }
        ],
        postLoaders: [
          {
            test: /\.js$/,
            exclude: [/node_modules/, /vendor/, /lib/, /dist/, /test/],
            loader: 'istanbul-instrumenter'
          }
        ]
      }
    },

    webpackMiddleware: {
      noInfo: true
    }
  });
};
<commit_msg>that wasn't hurting anything<commit_after>var path = require('path');
var webpack = require('webpack');
var defaults = require('./defaults');
var browserStackBrowsers = require('./browserstack.browsers');

var defaultsPlugin = new webpack.DefinePlugin(defaults);

var allBrowsers = browserStackBrowsers.filter('bs_all');
var allBrowsersByBrowser = {};
allBrowsers.forEach(function(browser) {
  allBrowsersByBrowser[browser._alias] = browser;
});

module.exports = function (config) {
  config.set({
    browsers: ['PhantomJS'],

    // The Travis environment has these specified.
    // To run BrowserStack tests locally, specify the environment variables:
    //  BROWSER_STACK_USERNAME, BROWSER_STACK_ACCESS_KEY
    browserStack: {
      username: null,
      accessKey: null
    },

    client: {
      captureConsole: true
    },

    // Used for testing on BrowserStack
    customLaunchers: allBrowsersByBrowser,

    // Files are specified in the grunt-karma configuration in Gruntfile.js
    //files: []

    frameworks: ['mocha', 'expect', 'sinon', 'jquery-1.9.0'],

    logLevel: 'INFO',

    // Default is 1000 but we can run into rate limit issues so bump it up to 10k
    pollingTimeout: 10000,

    // run the bundle through the webpack and sourcemap plugins
    preprocessors: {
      'test-browser/!(requirejs).test.js': ['webpack'],
      'test/!(requirejs).test.js': ['webpack'],
      'src/**/*.js': ['coverage']
    },

    proxies: {
      '/dist/rollbar.js': '/base/dist/rollbar.js'
    },

    reporters: ['progress', 'coverage'],

    singleRun: true,

    // Use "polling" and JSONP for older browsers
    transports: ['polling'],
    forceJSONP: true,

    webpack: {
      eslint: {
        configFile: path.resolve(__dirname, ".eslintrc")
      },
      plugins: [defaultsPlugin],
      module: {
        preLoaders: [
          {
            test: /\.js$/,
            loader: "strict!eslint",
            exclude: [/node_modules/, /vendor/, /lib/, /dist/]
          }
        ],
        loaders: [
          {
            test: /(mootootls|requirejs)\.js$/,
            loader: 'script'
          }
        ],
        postLoaders: [
          {
            test: /\.js$/,
            exclude: [/node_modules/, /vendor/, /lib/, /dist/, /test/],
            loader: 'istanbul-instrumenter'
          }
        ]
      }
    },

    webpackMiddleware: {
      noInfo: true
    }
  });
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function(app, passport) {

    // Home route
    var index = require('../controllers/index');
    app.get('/', index.render);

};
<commit_msg>require a session for any access to the app<commit_after>'use strict';

var authorization = require('./middlewares/authorization');

module.exports = function(app, passport) {

    // Home route
    var index = require('../controllers/index');
    app.get('/', authorization.requiresLogin, index.render);

};
<|endoftext|>


<commit_before>/* eslint-env browser, jquery */
/* global filterXSS */
// allow some attributes
var whiteListAttr = ['id', 'class', 'style']
window.whiteListAttr = whiteListAttr
// allow link starts with '.', '/' and custom protocol with '://', exclude link starts with javascript://
var linkRegex = /^(?!javascript:\/\/)([\w|-]+:\/\/)|^([.|/])+/i
// allow data uri, from https://gist.github.com/bgrins/6194623
var dataUriRegex = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)\s*$/i
// custom white list
var whiteList = filterXSS.whiteList
// allow ol specify start number
whiteList['ol'] = ['start']
// allow li specify value number
whiteList['li'] = ['value']
// allow style tag
whiteList['style'] = []
// allow kbd tag
whiteList['kbd'] = []
// allow ifram tag with some safe attributes
whiteList['iframe'] = ['allowfullscreen', 'name', 'referrerpolicy', 'sandbox', 'src', 'srcdoc', 'width', 'height']
// allow summary tag
whiteList['summary'] = []

var filterXSSOptions = {
  allowCommentTag: true,
  whiteList: whiteList,
  escapeHtml: function (html) {
    // allow html comment in multiple lines
    return html.replace(/<(?!!--)/g, '<').replace(/-->/g, '__HTML_COMMENT_END__').replace(/>/g, '>').replace(/__HTML_COMMENT_END__/g, '-->')
  },
  onIgnoreTag: function (tag, html, options) {
    // allow comment tag
    if (tag === '!--') {
            // do not filter its attributes
      return html
    }
  },
  onTagAttr: function (tag, name, value, isWhiteAttr) {
    // allow href and src that match linkRegex
    if (isWhiteAttr && (name === 'href' || name === 'src') && linkRegex.test(value)) {
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
    // allow data uri in img src
    if (isWhiteAttr && (tag === 'img' && name === 'src') && dataUriRegex.test(value)) {
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
  },
  onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
    // allow attr start with 'data-' or in the whiteListAttr
    if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) {
      // escape its value using built-in escapeAttrValue function
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
  }
}

function preventXSS (html) {
  return filterXSS(html, filterXSSOptions)
}
window.preventXSS = preventXSS

module.exports = {
  preventXSS: preventXSS
}
<commit_msg>Prevent XSS vul by srcdoc in iframe<commit_after>/* eslint-env browser, jquery */
/* global filterXSS */
// allow some attributes
var whiteListAttr = ['id', 'class', 'style']
window.whiteListAttr = whiteListAttr
// allow link starts with '.', '/' and custom protocol with '://', exclude link starts with javascript://
var linkRegex = /^(?!javascript:\/\/)([\w|-]+:\/\/)|^([.|/])+/i
// allow data uri, from https://gist.github.com/bgrins/6194623
var dataUriRegex = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)\s*$/i
// custom white list
var whiteList = filterXSS.whiteList
// allow ol specify start number
whiteList['ol'] = ['start']
// allow li specify value number
whiteList['li'] = ['value']
// allow style tag
whiteList['style'] = []
// allow kbd tag
whiteList['kbd'] = []
// allow ifram tag with some safe attributes
whiteList['iframe'] = ['allowfullscreen', 'name', 'referrerpolicy', 'sandbox', 'src', 'width', 'height']
// allow summary tag
whiteList['summary'] = []

var filterXSSOptions = {
  allowCommentTag: true,
  whiteList: whiteList,
  escapeHtml: function (html) {
    // allow html comment in multiple lines
    return html.replace(/<(?!!--)/g, '<').replace(/-->/g, '__HTML_COMMENT_END__').replace(/>/g, '>').replace(/__HTML_COMMENT_END__/g, '-->')
  },
  onIgnoreTag: function (tag, html, options) {
    // allow comment tag
    if (tag === '!--') {
            // do not filter its attributes
      return html
    }
  },
  onTagAttr: function (tag, name, value, isWhiteAttr) {
    // allow href and src that match linkRegex
    if (isWhiteAttr && (name === 'href' || name === 'src') && linkRegex.test(value)) {
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
    // allow data uri in img src
    if (isWhiteAttr && (tag === 'img' && name === 'src') && dataUriRegex.test(value)) {
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
  },
  onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
    // allow attr start with 'data-' or in the whiteListAttr
    if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) {
      // escape its value using built-in escapeAttrValue function
      return name + '="' + filterXSS.escapeAttrValue(value) + '"'
    }
  }
}

function preventXSS (html) {
  return filterXSS(html, filterXSSOptions)
}
window.preventXSS = preventXSS

module.exports = {
  preventXSS: preventXSS
}
<|endoftext|>


<commit_before>require keys from './config/apikeys.js';

var fb_userToken = keys.fb_userToken;
var fb_ID = keys.fb_ID;

var tinder = require('tinderjs');
var client = new tinder.TinderClient();

var fb_userToken =

client.authorize(
  fb_userToken,
  fb_ID,
  function() {
    client.getRecommendations(10, function(error, data){
      console.log(data.results);
    });
  });
});<commit_msg>successful tinder auth and 10 profiles<commit_after>var keys = require('../config/apikeys');

var fb_userToken = keys.fb_userToken;
var fb_ID = keys.fb_ID;

var tinder = require('tinderjs');
var client = new tinder.TinderClient();

var fb_userToken =

client.authorize(
  fb_userToken,
  fb_ID,
  function() {
    client.getRecommendations(10, function(error, data){
      console.log(data.results);
    });
  }
);
<|endoftext|>


<commit_before>/* jshint strict:false */
/* global define */

(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define([
            'object-assign',
            'hawk',
            'renameKeys',
            './authentication',
            './scans'
        ], function(
            ObjectAssign,
            hawk,
            rename,
            authentication,
            scans
        ) {
            return factory(
                ObjectAssign.assign,
                hawk,
                rename,
                localStorage,
                authentication,
                scans
            );
        });
    } else if (typeof module === 'object' && module.exports) {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        var storage = (function() {
            if (typeof localStorage !== 'undefined') {
                return localStorage;
            }

            var Storage = require('dom-storage');

            return new Storage(null, { strict: true });
        })();

        module.exports = factory(
            require('es6-object-assign').assign,
            require('hawk/lib/browser.js'),
            require('rename-keys'),
            storage,
            require('./authentication'),
            require('./scans')
        );

    } else {
        // Browser globals (root is window)
        root.CoinsApiClient = factory(
            root.ObjectAssign.assign,
            root.hawk,
            root.rename,
            root.localStorage,
            root.CoinsApiClient.authentication,
            root.CoinsApiClient.scans
        );

    }
}(this, function(

    assign,
    hawk,
    renameKeys,
    localStorage,
    authentication,
    scans
) {
    'use strict';

    // TODO use semver to autmatically append to url
    var hawkClientHeader = hawk.client.header;
    var authKeyId = 'COINS_AUTH_CREDENTIALS';
    var defaultConfig = {
        requestFn: null,
        requestObjectMap: {
            method: 'method',
            body: 'body',
            headers: 'headers',
            uri: 'uri'
        },
        baseUrl: 'https://coins-api.mrn.org/api',
        version: null,
        formatRequestHeaders: function(value) {
            return value;
        },

        formatResponseCallback: function(respArray) {
            respArray[0].body = JSON.parse(respArray[0].body);
            return respArray[0];
        }
    };
    var me = {};

    /**
     * get the currently stored auth credentials
     * @return {Promise}        resolves to the credentials object
     */
    var getAuthCredentials = function() {
        return new Promise(function(resolve) {
            resolve(JSON.parse(localStorage.getItem(authKeyId)));
        });
    };

    /**
     * set auth credentials
     * @param  {object} val the credentials to be saved
     * @return {Promise}    resolves to an object containing the id and rev
     */
    var setAuthCredentials = function(credentials) {
        return new Promise(function(resolve) {
            localStorage.setItem(authKeyId, JSON.stringify(credentials));
            resolve(getAuthCredentials());
        });
    };

    /**
     * generate the header expected by Hawk.
     * Note that the url must include a protocol and hostname
     * @param  {string} url
     * @param  {string} method e.g. 'GET'
     * @return {string} The hawk auth signature
     */
    var generateHawkHeader = function(url, method) {
        return me.getAuthCredentials()
            .then(function(credentials) {
                if (!credentials) {
                    throw new Error('No credentials found to sign with');
                }

                return me.getHawkHeader(
                    url,
                    method,
                    { credentials: credentials }
                );
            });
    };

    /**
     * format requestObj for use by requestFn
     * @param  {object} requestObj the object to be passed to the requestFn
     * @return {object}            the object after mapping keys to new ones
     */
    var formatRequestOptions = function(requestOptions) {
        if (me.config.onPreFormatRequestOptions instanceof Function) {
            requestOptions = me.config.onPreFormatRequestOptions(
                requestOptions
            );
        }

        requestOptions.uri = [
            me.config.baseUrl,
            '/v' + me.config.version,
            requestOptions.uri
        ].join('');

        return renameKeys(requestOptions, function(key) {
            return me.config.requestObjectMap[key] || key;
        });
    };

    /**
     * make a request using config.requestFn
     * @param  {object} options request options to be passed to requestFn
     * @return {Promise}        promise that resolves with the value of the
     *                          response
     */
    var makeRequest = function(options, sign) {
        var formattedOptions = formatRequestOptions(options);

        /**
         * convenience function for sending the formatted request
         * @return {Promise} resolves to the formatted response value
         */
        var sendRequest = function() {
            return me.config.requestFn(formattedOptions)
                .then(me.config.formatResponseCallback);
        };

        /**
         * convenience function for adding a header property to the
         * formattedOptions
         * @param  {object} header output from hawk.client.header();
         * @return {null}        nothing
         */
        var addFormattedHeader = function(header) {
            var headers = formattedOptions.headers || [];
            headers.push({
                name: 'Authorization',
                value: header.field
            });
            formattedOptions.headers = me.config.formatRequestHeaders(headers);
            return;
        };

        var masterPromise;
        if (sign !== false) {
            masterPromise = generateHawkHeader(
                formattedOptions.url,
                formattedOptions.method
            )
                .then(addFormattedHeader);
        } else {
            masterPromise = Promise.resolve();
        }

        return masterPromise.then(sendRequest);
    };

    return function init(config) {
        me.config = assign({}, defaultConfig, config);
        me.getHawkHeader = hawkClientHeader;
        me.generateHawkHeader = generateHawkHeader;
        me.makeRequest = makeRequest;
        me.setAuthCredentials = setAuthCredentials;
        me.getAuthCredentials = getAuthCredentials;
        me.auth = authentication(me);
        me.scans = scans(me);
        return me;
    };
}));
<commit_msg>Update SDK's AMD module names.<commit_after>/* jshint strict:false */
/* global define */

(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define([
            'es6-object-assign',
            'hawk',
            'rename-keys',
            './authentication',
            './scans'
        ], function(
            ObjectAssign,
            hawk,
            rename,
            authentication,
            scans
        ) {
            return factory(
                ObjectAssign.assign,
                hawk,
                rename,
                localStorage,
                authentication,
                scans
            );
        });
    } else if (typeof module === 'object' && module.exports) {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        var storage = (function() {
            if (typeof localStorage !== 'undefined') {
                return localStorage;
            }

            var Storage = require('dom-storage');

            return new Storage(null, { strict: true });
        })();

        module.exports = factory(
            require('es6-object-assign').assign,
            require('hawk/lib/browser.js'),
            require('rename-keys'),
            storage,
            require('./authentication'),
            require('./scans')
        );

    } else {
        // Browser globals (root is window)
        root.CoinsApiClient = factory(
            root.ObjectAssign.assign,
            root.hawk,
            root.rename,
            root.localStorage,
            root.CoinsApiClient.authentication,
            root.CoinsApiClient.scans
        );

    }
}(this, function(

    assign,
    hawk,
    renameKeys,
    localStorage,
    authentication,
    scans
) {
    'use strict';

    // TODO use semver to autmatically append to url
    var hawkClientHeader = hawk.client.header;
    var authKeyId = 'COINS_AUTH_CREDENTIALS';
    var defaultConfig = {
        requestFn: null,
        requestObjectMap: {
            method: 'method',
            body: 'body',
            headers: 'headers',
            uri: 'uri'
        },
        baseUrl: 'https://coins-api.mrn.org/api',
        version: null,
        formatRequestHeaders: function(value) {
            return value;
        },

        formatResponseCallback: function(respArray) {
            respArray[0].body = JSON.parse(respArray[0].body);
            return respArray[0];
        }
    };
    var me = {};

    /**
     * get the currently stored auth credentials
     * @return {Promise}        resolves to the credentials object
     */
    var getAuthCredentials = function() {
        return new Promise(function(resolve) {
            resolve(JSON.parse(localStorage.getItem(authKeyId)));
        });
    };

    /**
     * set auth credentials
     * @param  {object} val the credentials to be saved
     * @return {Promise}    resolves to an object containing the id and rev
     */
    var setAuthCredentials = function(credentials) {
        return new Promise(function(resolve) {
            localStorage.setItem(authKeyId, JSON.stringify(credentials));
            resolve(getAuthCredentials());
        });
    };

    /**
     * generate the header expected by Hawk.
     * Note that the url must include a protocol and hostname
     * @param  {string} url
     * @param  {string} method e.g. 'GET'
     * @return {string} The hawk auth signature
     */
    var generateHawkHeader = function(url, method) {
        return me.getAuthCredentials()
            .then(function(credentials) {
                if (!credentials) {
                    throw new Error('No credentials found to sign with');
                }

                return me.getHawkHeader(
                    url,
                    method,
                    { credentials: credentials }
                );
            });
    };

    /**
     * format requestObj for use by requestFn
     * @param  {object} requestObj the object to be passed to the requestFn
     * @return {object}            the object after mapping keys to new ones
     */
    var formatRequestOptions = function(requestOptions) {
        if (me.config.onPreFormatRequestOptions instanceof Function) {
            requestOptions = me.config.onPreFormatRequestOptions(
                requestOptions
            );
        }

        requestOptions.uri = [
            me.config.baseUrl,
            '/v' + me.config.version,
            requestOptions.uri
        ].join('');

        return renameKeys(requestOptions, function(key) {
            return me.config.requestObjectMap[key] || key;
        });
    };

    /**
     * make a request using config.requestFn
     * @param  {object} options request options to be passed to requestFn
     * @return {Promise}        promise that resolves with the value of the
     *                          response
     */
    var makeRequest = function(options, sign) {
        var formattedOptions = formatRequestOptions(options);

        /**
         * convenience function for sending the formatted request
         * @return {Promise} resolves to the formatted response value
         */
        var sendRequest = function() {
            return me.config.requestFn(formattedOptions)
                .then(me.config.formatResponseCallback);
        };

        /**
         * convenience function for adding a header property to the
         * formattedOptions
         * @param  {object} header output from hawk.client.header();
         * @return {null}        nothing
         */
        var addFormattedHeader = function(header) {
            var headers = formattedOptions.headers || [];
            headers.push({
                name: 'Authorization',
                value: header.field
            });
            formattedOptions.headers = me.config.formatRequestHeaders(headers);
            return;
        };

        var masterPromise;
        if (sign !== false) {
            masterPromise = generateHawkHeader(
                formattedOptions.url,
                formattedOptions.method
            )
                .then(addFormattedHeader);
        } else {
            masterPromise = Promise.resolve();
        }

        return masterPromise.then(sendRequest);
    };

    return function init(config) {
        me.config = assign({}, defaultConfig, config);
        me.getHawkHeader = hawkClientHeader;
        me.generateHawkHeader = generateHawkHeader;
        me.makeRequest = makeRequest;
        me.setAuthCredentials = setAuthCredentials;
        me.getAuthCredentials = getAuthCredentials;
        me.auth = authentication(me);
        me.scans = scans(me);
        return me;
    };
}));
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Wed Jan 28 2015 19:14:37 GMT-0700 (MST)

const webpackConfig = require('./webpack.config')

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: [ 'mocha', 'chai' ],

    // list of files / patterns to load in the browser
    files: [
      'test/**/*.spec.js'
    ],

    // list of files to exclude
    exclude: [
			'test/**/*.cli.spec.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
			'test/**/*.js': [ 'webpack', 'sourcemap' ]
    },

		webpack: {
			cache: true,
			devtool: '#inline-source-map',
			module: {
				loaders: webpackConfig.module.loaders
			}
		},

		webpackMiddleware: {
			noInfo: true
		},

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: [ 'dots' ],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_WARN,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [ 'Chrome', 'Firefox', 'Safari', 'PhantomJS' ],
		browserNoActivityTimeout: 20000,

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true
  })
}
<commit_msg>[internal] give karma longer, use consistent whitespace<commit_after>// Karma configuration
// Generated on Wed Jan 28 2015 19:14:37 GMT-0700 (MST)

const webpackConfig = require('./webpack.config')

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: [ 'mocha', 'chai' ],

    // list of files / patterns to load in the browser
    files: [
      'test/**/*.spec.js'
    ],

    // list of files to exclude
    exclude: [
      'test/**/*.cli.spec.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'test/**/*.js': [ 'webpack', 'sourcemap' ]
    },

    webpack: {
      cache: true,
      devtool: '#inline-source-map',
      module: {
        loaders: webpackConfig.module.loaders
      }
    },

    webpackMiddleware: {
      noInfo: true
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: [ 'dots' ],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_WARN,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [ 'Chrome', 'Firefox', 'Safari', 'PhantomJS' ],
    browserNoActivityTimeout: 30000,

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true
  })
}
<|endoftext|>


<commit_before>'use strict';

var path = process.cwd();
var Yelp = require('yelp');
var multer  = require('multer');
var upload = multer({ dest: 'uploads/' });
var handlebars  = require('handlebars');
var fs = require('fs');
var session = require('express-session');
var Users = require('../models/users.js');
var Nightclubs = require('../models/nightlife.js');

module.exports = function (app, passport) {

//Express middleware checks log in status
function isLoggedIn (req, res, next) {
        if (req.isAuthenticated()) {
            return next();
        } else {
            res.redirect('/login');
        }
    }

//Yelp keys
var yelp = new Yelp({
  consumer_key: process.env.YELP_KEY,
  consumer_secret: process.env.YELP_SECRET,
  token: process.env.YELP_TOKEN,
  token_secret: process.env.YELP_TOKEN_SECRET,
});

	app.route('/')
		.get(function (req, res) {
		   var loggedin;
             if (req.isAuthenticated()) {
                 loggedin = true;
             } else {
                  loggedin = false;
             }
//	console.log(req.session.passport.user)
		var data = {
                loggedin: loggedin
           }
    //loads index with no nightlife data
        fs.readFile('public/index.html', 'utf-8', function(error, source){
                var template = handlebars.compile(source);
                var html = template(data);
                res.send(html);

                });
		});

app.post('/',  upload.array(), function (req, res, next) {
		console.log("location:" + req.body["location"]);
		   var loggedin;
             if (req.isAuthenticated()) {
                 loggedin = true;
             } else {
                  loggedin = false;
             }
	//	console.log("user" + res.user);

		yelp.search({ term: 'nightlife', location: req.body["location"] })
				.then(function (data) {
					var biz="
"

  					for (var i=0; i< data.businesses.length; i++){
  					    //for each biz id I should find if the id exists. if it doesn't I can assume no one is there. I'm choosing to only create id on check in to save space.

                             var url =  data.businesses[i].url;
  						     var name = data.businesses[i].name;
  						     var imgURL = data.businesses[i].image_url;
  					    	 var snippet = data.businesses[i].snippet_text;

                            var getTheSearch = function (callback){
                                var partygoers;

  		                         Nightclubs.findOne({ 'id': data.businesses[i].id }, function (err, nightclub) {
                                    if (err) throw err;
                                    if(nightclub){
                                        partygoers = nightclub.users.length;
                                    //TODO add in what to do if I'M going to the nightclub
                                    //if (req.user ...)
                                    } else {
                                         partygoers = 0;
                                    }
                                    callback(partygoers);
                                });

                            }

                            var formatting = function(partygoers){
                                biz+="

";
                                biz+= name +"
";
  	                            biz+= "";
  	                            biz += snippet;
  	                             biz += partygoers + " people give a hoot!"
  	                             biz +="
"

  	                         console.log(biz);
                            }

                            	getTheSearch(formatting);

  					}

  					            //inserts biz info via handlebars
  				            	var data = {
  						            nightlife: biz,
  					            	loggedin: loggedin
           		            	}
           		            	fs.readFile('public/index.html', 'utf-8', function(error, source){
            			             var template = handlebars.compile(source);
                		            var html = template(data);
                		             res.send(html);
               	            	});

				})
			   .catch(function (err) {
  					console.error(err);
				});

});

app.route('/login')
    .get(function (req, res) {
        res.sendFile(path + '/public/login.html');
    });

app.route('/logout')
    .get(function (req, res) {
        req.logout();
        res.redirect('/login');
    });

app.route('/auth/twitter')
    .get(passport.authenticate('twitter'));

app.route('/auth/twitter/callback')
    .get(passport.authenticate('twitter', {
        successRedirect: '/',
        failureRedirect: '/login'
    }));

};

<commit_msg>callback variable passthroughs<commit_after>'use strict';

var path = process.cwd();
var Yelp = require('yelp');
var multer  = require('multer');
var upload = multer({ dest: 'uploads/' });
var handlebars  = require('handlebars');
var fs = require('fs');
var session = require('express-session');
var Users = require('../models/users.js');
var Nightclubs = require('../models/nightlife.js');

module.exports = function (app, passport) {

//Express middleware checks log in status
function isLoggedIn (req, res, next) {
        if (req.isAuthenticated()) {
            return next();
        } else {
            res.redirect('/login');
        }
    }

//Yelp keys
var yelp = new Yelp({
  consumer_key: process.env.YELP_KEY,
  consumer_secret: process.env.YELP_SECRET,
  token: process.env.YELP_TOKEN,
  token_secret: process.env.YELP_TOKEN_SECRET,
});

	app.route('/')
		.get(function (req, res) {
		   var loggedin;
             if (req.isAuthenticated()) {
                 loggedin = true;
             } else {
                  loggedin = false;
             }
//	console.log(req.session.passport.user)
		var data = {
                loggedin: loggedin
           }
    //loads index with no nightlife data
        fs.readFile('public/index.html', 'utf-8', function(error, source){
                var template = handlebars.compile(source);
                var html = template(data);
                res.send(html);

                });
		});

app.post('/',  upload.array(), function (req, res, next) {
		console.log("location:" + req.body["location"]);
		   var loggedin;
             if (req.isAuthenticated()) {
                 loggedin = true;
             } else {
                  loggedin = false;
             }
	//	console.log("user" + res.user);

		yelp.search({ term: 'nightlife', location: req.body["location"] })
				.then(function (data) {
					var biz="
"

  					for (var i=0; i< data.businesses.length; i++){
  					    //for each biz id I should find if the id exists. if it doesn't I can assume no one is there. I'm choosing to only create id on check in to save space.

                             var url =  data.businesses[i].url;
  						     var name = data.businesses[i].name;
  						     var imgURL = data.businesses[i].image_url;
  					    	 var snippet = data.businesses[i].snippet_text;

                            var getTheSearch = function (callback, url, name, imgURL, snippet){
                                var partygoers;

  		                         Nightclubs.findOne({ 'id': data.businesses[i].id }, function (err, nightclub) {
                                    if (err) throw err;
                                    if(nightclub){
                                        partygoers = nightclub.users.length;
                                    //TODO add in what to do if I'M going to the nightclub
                                    //if (req.user ...)
                                    } else {
                                         partygoers = 0;
                                    }
                                    callback(partygoers, url,name, imgURL, snippet);
                                });

                            }

                            var formatting = function(partygoers, url, name, imgURL, snippet){
                                biz+="

";
                                biz+= name +"
";
  	                            biz+= "";
  	                            biz += snippet;
  	                             biz += partygoers + " people give a hoot!"
  	                             biz +="
"
  	                            console.log(biz);
                            }

                            	getTheSearch(formatting, url, name, imgURL, snippet);

  					}

  					            //inserts biz info via handlebars
  				            	var data = {
  						            nightlife: biz,
  					            	loggedin: loggedin
           		            	}
           		            	fs.readFile('public/index.html', 'utf-8', function(error, source){
            			             var template = handlebars.compile(source);
                		            var html = template(data);
                		             res.send(html);
               	            	});

				})
			   .catch(function (err) {
  					console.error(err);
				});

});

app.route('/login')
    .get(function (req, res) {
        res.sendFile(path + '/public/login.html');
    });

app.route('/logout')
    .get(function (req, res) {
        req.logout();
        res.redirect('/login');
    });

app.route('/auth/twitter')
    .get(passport.authenticate('twitter'));

app.route('/auth/twitter/callback')
    .get(passport.authenticate('twitter', {
        successRedirect: '/',
        failureRedirect: '/login'
    }));

};

<|endoftext|>


<commit_before>/**
 * 路由
 */
var utils = require('../utils');
var simi = require('../services/simi');

exports.home = function* () {
  this.body = 'hello world';
  this.status = 200;
};

exports.handle = function* () {
  var content = this.request.body;
  console.log(content)
  var trigger_word = content.trigger_word;
  var text = content.text;
  if (text.indexOf('!') === 0) {
    return this.body = {};
  }
  if (trigger_word === 'test') {
    yield utils.getImg('http://finance.sina.com.cn/stock/','test2', '#wmt_contents', 'iphone 5s');
    this.body = {
      text: 'http://i.imgur.com/JQ8GA1p.jpg',
      "attachments": [
        {
          "fallback": "Network traffic (kb/s): How does this look? @slack-ops - Sent by Julie Dodd - https://datadog.com/path/to/event",
          "title": "Network traffic (kb/s)",
          "title_link": "https://datadog.com/path/to/event",
          "text": "How does this look? @slack-ops - Sent by Julie Dodd",
          "image_url": "http://i.imgur.com/JQ8GA1p.jpg",
          "color": "#764FA5"
        }
      ]
    };
  }
  if (text) {
    var reply = yield simi.chat(text) || '呵呵';
    console.log(reply)
    return this.body = {
      text: '!' + reply
    };
  }
};<commit_msg>add simi<commit_after>/**
 * 路由
 */
var utils = require('../utils');
var simi = require('../services/simi');

exports.home = function* () {
  this.body = 'hello world';
  this.status = 200;
};

exports.handle = function* () {
  var content = this.request.body;
  console.log(content)
  var trigger_word = content.trigger_word;
  var text = content.text;
  if (text.indexOf('!') === 0) {
    return this.body = {};
  }
  if (trigger_word === 'test') {
    yield utils.getImg('http://finance.sina.com.cn/stock/','test2', '#wmt_contents', 'iphone 5s');
    this.body = {
      text: 'http://i.imgur.com/JQ8GA1p.jpg',
      "attachments": [
        {
          "fallback": "Network traffic (kb/s): How does this look? @slack-ops - Sent by Julie Dodd - https://datadog.com/path/to/event",
          "title": "Network traffic (kb/s)",
          "title_link": "https://datadog.com/path/to/event",
          "text": "How does this look? @slack-ops - Sent by Julie Dodd",
          "image_url": "http://i.imgur.com/JQ8GA1p.jpg",
          "color": "#764FA5"
        }
      ]
    };
  }
  if (text) {
    var reply = (yield simi.chat(text)) || '呵呵';
    console.log(reply)
    return this.body = {
      text: '!' + reply
    };
  }
};<|endoftext|>