<commit_before>// load the master sakai object to access all Sakai OAE API methods
require(["jquery",
         "sakai/sakai.api.core",
         "/devwidgets/lecturelist/javascript/jquery.icalendar.js",
         "/devwidgets/lecturelist/javascript/parseuri.js"],
        function($, sakai) {

    /**
     * @name sakai.WIDGET_ID
     *
     * @class WIDGET_ID
     *
     * @description
     * WIDGET DESCRIPTION
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
	sakai_global.lecturelist = function (tuid, showSettings) {

		var ICAL_PROXY_PATH = "/var/proxy/ical.json"

		var LECTURE_ENTRY = $("#lecturelist_templates .entry", $rootel);
		var AGENDA_ROW = $("#lecturelist_templates .agenda-row", $rootel);
		/////////////////////////////
        // Configuration variables //
        /////////////////////////////

    	// DOM jQuery Objects
        var $rootel = $("#" + tuid);  // unique container for each widget instance
        var $mainContainer = $("#lecturelist_main", $rootel);
        var $settingsContainer = $("#lecturelist_settings", $rootel);
        var settingsForm = $("#lecturelist_settings_form", $rootel);
        var settingsFormTitleField = $("#lecturelist_settings_txtTitle", $rootel);
        var settingsFormUrlField = $("#lecturelist_settings_txtUrl", $rootel);

        // Widget state vars
        var _title = null;
        var _feedUrl = null;
        var _groupedDays = null;

        DAYS = {"0": "Mon",
        		"1": "Tue",
        		"2": "Wed",
        		"3": "Thu",
        		"4": "Fri",
        		"5": "Sat",
        		"6": "Sun"};

        MONTHS = {"0": "Jan",
        		  "1": "Feb",
        		  "2": "Mar",
        		  "3": "Apr",
        		  "4": "May",
        		  "5": "Jun",
        		  "6": "Jul",
        		  "7": "Aug",
        		  "8": "Sep",
        		  "9": "Oct",
        		  "10": "Nov",
        		  "11": "Dec"};

        var TODAY = dateToday();

        /**
         * A class to represent events.
         */
    	function Event(vevent) {

    		function paragraphBreak(text) {
    			// Break the text on blank lines
    			return text.split(/^\s*$/m);
    		}

    		this.vevent = vevent;
    		this.absDate = buildAbsoluteDateString(vevent.DTSTART);
    		this.dayDelta = getDayDelta(TODAY, vevent.DTSTART);
    		this.relDate = buildRelativeDateString(this.dayDelta);
    		this.time = buildTimeString(vevent.DTSTART);
    		this.summary = vevent.SUMMARY || vevent.DESCRIPTION || "";
    		this.description = vevent.DESCRIPTION || vevent.SUMMARY || "";
    		if(this.description == this.summary) {
    			this.description = "";
    		}
    		this.description = paragraphBreak(this.description);

    		// These fields may be undefined
    		this.url = vevent.URL;
    		this.location = vevent.LOCATION;
    		this.contact = vevent.CONTACT;
    	}

        ///////////////////////
        // Utility functions //
        ///////////////////////

        function onStateAvailable(succeeded, state) {
        	if(!succeeded) {
        		alert("Failed to fetch widget state.");
        		return;
        	}

        	_title = state.title;
        	_feedUrl = state.url;
        	fetchCalendarData();
        }

        function fetchCalendarData() {
        	var success = function(data) {
        		if(data.vcalendar && data.vcalendar.vevents) {
        			var events = data.vcalendar.vevents;

        			// Convert event date strings into date objects
        			events = $.map(events, parseEventDates);

        			// Filter the events to just those happening today
        			//events = $.grep(events, notBefore(dateToday()));

        			// Group the events into a list of groups, one for each day
        			_groupedDays = groupByDay(events);

        		}
        		updateCalendar();
        	};

        	$.ajax({
        		url: ICAL_PROXY_PATH,
        		data: {feedurl: _feedUrl},
        		success: success});
        }

        function parseEventDates(event) {
        	event.DTSTART = new Date(event.DTSTART);
        	event.DTEND = new Date(event.DTEND);
        	return event;
        }

        function dateToday() {
        	return stripTime(new Date());
        }
        function dateTomorrow() {
        	var today = dateToday();
        	today.setDate(today.getDate() + 1);
        	return today;
        }

        function notBefore(date) {
        	return function(event) {
        		return event.DTSTART >= date;
        	}
        }

        function between(dateStart, dateEnd) {
        	return function(event) {
        		return event.dtstart >= dateStart && event.dstart < dateEnd;
        	}
        }

        function groupByDay(vevents) {
        	var days = {}
        	for(var i = 0; i < vevents.length; ++i) {
        		var event = vevents[i];
        		// We need a string to key our obj with
        		var dateKey = stripTime(event.DTSTART).toISOString();
        		if(!days[dateKey]) {
        			days[dateKey] = []
        		}
        		days[dateKey].push(new Event(event));
        	}
        	var sortedDays = [];
        	for(key in days) {
        		var events = days[key];
        		events.sort(function(a, b){
        			return a.vevent.DTSTART.milliseconds - b.vevent.DTSTART.milliseconds;
        		});
        		sortedDays.push([key, events]);
        	}
        	sortedDays.sort(function(a, b) {
        		if(a[0] < b[0])
        			return -1;
        		else if(a[0] > b[0])
        			return 1;
        		return 0;
        	});

        	return sortedDays;
        }

        function stripTime(date) {
        	return new Date(date.getFullYear(), date.getMonth(),
        			date.getDate());
        }

        /**
         * Loads widget saved state, calling the callback(success, data)
         * function once the state is loaded.
         */
        function getState(callback) {
        	sakai.api.Widgets.loadWidgetData(tuid, callback);
        }

        /////////////////////////
        // Main View functions //
        /////////////////////////

        /** Called when the calendar data has been updated. */
        function updateCalendar() {

        	var rendered = sakai.api.Util.TemplateRenderer("#agenda_template", {
				title: _title,
				days: _groupedDays
			});

        	$(".ajax-content", $rootel).html(rendered);
        	$(".ajax-content .summary.compact", $rootel).toggle(
        			expandCalendarEntry, contractCalendarEntry);
        	$(".loading", $rootel).hide();
        	$(".ajax-content", $rootel).show();
        }

        function buildTimeString(date) {
        	var hour = date.getHours();
        	var minute = "" + date.getMinutes();
        	if(minute.length === 1)
        		minute = "0" + minute;
        	return hour + ":" + minute;
        }

        // Length of one day in milliseconds
        var DAY_MILLIS = 1000*60*60*24;
        var MAX_DAYS_AGO = 5;

        function getDayDelta(from, to) {
        	// Millisecond time @ start of today
        	var fromms = stripTime(from).getTime();
        	var toms = stripTime(to).getTime();
        	// Calculate number of days between from and to.
        	return Math.floor((toms - fromms) / DAY_MILLIS);
        }

        /**
         * Builds a relative date string from an integer day delta. Day deltas
         * can be calculated by getDayDelta().
         *
         * For example:
         * buildRelativeDateString(0) => "Today"
         * buildRelativeDateString(-1) => "Yesterday"
         * buildRelativeDateString(1) => "Tomorrow"
         * buildRelativeDateString(-10) => "10 days ago"
         * buildRelativeDateString(10) => "In 10 days"
         */
        function buildRelativeDateString(delta) {
        	// make sure we have an integer
        	var days = Math.floor(delta);
        	if(days == 0)
				return "Today";
			else if(days == 1)
				return "Tomorrow";
			else if(days == -1)
				return "Yesterday";
			else if(days < 0)
				return "" + Math.abs(days) + " days ago";
			else
				return "In " + days + " time";

        }

        function buildAbsoluteDateString(date) {
        	var dayName = DAYS[date.getDay()];
        	var dayNumber = date.getDate();
        	var monthName = MONTHS[date.getMonth()];
        	return dayName + " " + dayNumber + " " + monthName;
        }

        function expandCalendarEntry(jqevent) {
        	var summary = $(this);
        	var expanded = summary.siblings(".full");

        	summary.removeClass("compact expandable").addClass("contractable");
        	expanded.slideDown();
        }

        function contractCalendarEntry(jqevent) {
        	var summary = $(this);
        	var expanded = summary.siblings(".full");

        	summary.addClass("compact expandable").removeClass("contractable");
        	expanded.slideUp();
        }

        /////////////////////////////
        // Settings View functions //
        /////////////////////////////

        /**
         * Watch for value changes to the settings URL field in order to rewrite
         * webcal:// urls to http://.
         */
        settingsFormUrlField.change(function() {
        	var urltext = $(this).val();
        	// Help people inputting webcal:// links by rewriting them to http
        	urltext = urltext.replace(/^webcal:\/\//, "http://")
        	$(this).val(urltext);
        });

        function onWidgetSettingsStateAvailable(success, state) {
        	if(success) {
	        	settingsFormTitleField.val(state.title);
	        	settingsFormUrlField.val(state.url);
        	}
        	else {
        		alert("Error fetching saved settings");
        	}
        }

        /** Add listener to setting form submit */
        function settingsSave() {
        	var state = {
        			title: 	settingsFormTitleField.val(),
        			url: settingsFormUrlField.val()
        	};

        	// async save our widget's state
        	sakai.api.Widgets.saveWidgetData(tuid, state,
        			onWidgetSettingsDataSaved);
        }

        function onWidgetSettingsDataSaved(success, data) {
        	if (success) {
        		// Settings finished, switch to Main view
        		sakai.api.Widgets.Container.informFinish(tuid, "lecturelist");
        	} else {
        		sakai.api.Util.notification.show("Couldn't Save Your Settings",
        				"An error prevented your settings from being saved. "
        				+ " Please try again.",
        				sakai.api.Util.notification.type.ERROR);
        	}
        }

        /////////////////////////////
        // Initialisation function //
        /////////////////////////////

        /**
         * Initialization function DOCUMENTATION
         */
        var doInit = function () {
            console.log("lecturelist doInit()");

            if (showSettings) {

            	// Setup validation on settings form
            	var validateOpts = { submitHandler: settingsSave };
                sakai.api.Util.Forms.validate(settingsForm, validateOpts, true);

                // Async fetch widget settings to populate form
                getState(onWidgetSettingsStateAvailable);

                // show the Settings view
                $settingsContainer.show();
            } else {
            	// set up Main view

            	// Async fetch widget settings to populate form
                getState(onStateAvailable);

            	$mainContainer.show();
            	$(".loading", $rootel).fadeIn(1000);
            }
        };

        // run the initialization function when the widget object loads
        doInit();
    };

    // inform Sakai OAE that this widget has loaded and is ready to run
    sakai.api.Widgets.widgetLoader.informOnLoad("lecturelist");
});
<commit_msg>Herp derp, typo in positive relative date string.<commit_after>// load the master sakai object to access all Sakai OAE API methods
require(["jquery",
         "sakai/sakai.api.core",
         "/devwidgets/lecturelist/javascript/jquery.icalendar.js",
         "/devwidgets/lecturelist/javascript/parseuri.js"],
        function($, sakai) {

    /**
     * @name sakai.WIDGET_ID
     *
     * @class WIDGET_ID
     *
     * @description
     * WIDGET DESCRIPTION
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
	sakai_global.lecturelist = function (tuid, showSettings) {

		var ICAL_PROXY_PATH = "/var/proxy/ical.json"

		var LECTURE_ENTRY = $("#lecturelist_templates .entry", $rootel);
		var AGENDA_ROW = $("#lecturelist_templates .agenda-row", $rootel);
		/////////////////////////////
        // Configuration variables //
        /////////////////////////////

    	// DOM jQuery Objects
        var $rootel = $("#" + tuid);  // unique container for each widget instance
        var $mainContainer = $("#lecturelist_main", $rootel);
        var $settingsContainer = $("#lecturelist_settings", $rootel);
        var settingsForm = $("#lecturelist_settings_form", $rootel);
        var settingsFormTitleField = $("#lecturelist_settings_txtTitle", $rootel);
        var settingsFormUrlField = $("#lecturelist_settings_txtUrl", $rootel);

        // Widget state vars
        var _title = null;
        var _feedUrl = null;
        var _groupedDays = null;

        DAYS = {"0": "Mon",
        		"1": "Tue",
        		"2": "Wed",
        		"3": "Thu",
        		"4": "Fri",
        		"5": "Sat",
        		"6": "Sun"};

        MONTHS = {"0": "Jan",
        		  "1": "Feb",
        		  "2": "Mar",
        		  "3": "Apr",
        		  "4": "May",
        		  "5": "Jun",
        		  "6": "Jul",
        		  "7": "Aug",
        		  "8": "Sep",
        		  "9": "Oct",
        		  "10": "Nov",
        		  "11": "Dec"};

        var TODAY = dateToday();

        /**
         * A class to represent events.
         */
    	function Event(vevent) {

    		function paragraphBreak(text) {
    			// Break the text on blank lines
    			return text.split(/^\s*$/m);
    		}

    		this.vevent = vevent;
    		this.absDate = buildAbsoluteDateString(vevent.DTSTART);
    		this.dayDelta = getDayDelta(TODAY, vevent.DTSTART);
    		this.relDate = buildRelativeDateString(this.dayDelta);
    		this.time = buildTimeString(vevent.DTSTART);
    		this.summary = vevent.SUMMARY || vevent.DESCRIPTION || "";
    		this.description = vevent.DESCRIPTION || vevent.SUMMARY || "";
    		if(this.description == this.summary) {
    			this.description = "";
    		}
    		this.description = paragraphBreak(this.description);

    		// These fields may be undefined
    		this.url = vevent.URL;
    		this.location = vevent.LOCATION;
    		this.contact = vevent.CONTACT;
    	}

        ///////////////////////
        // Utility functions //
        ///////////////////////

        function onStateAvailable(succeeded, state) {
        	if(!succeeded) {
        		alert("Failed to fetch widget state.");
        		return;
        	}

        	_title = state.title;
        	_feedUrl = state.url;
        	fetchCalendarData();
        }

        function fetchCalendarData() {
        	var success = function(data) {
        		if(data.vcalendar && data.vcalendar.vevents) {
        			var events = data.vcalendar.vevents;

        			// Convert event date strings into date objects
        			events = $.map(events, parseEventDates);

        			// Filter the events to just those happening today
        			//events = $.grep(events, notBefore(dateToday()));

        			// Group the events into a list of groups, one for each day
        			_groupedDays = groupByDay(events);

        		}
        		updateCalendar();
        	};

        	$.ajax({
        		url: ICAL_PROXY_PATH,
        		data: {feedurl: _feedUrl},
        		success: success});
        }

        function parseEventDates(event) {
        	event.DTSTART = new Date(event.DTSTART);
        	event.DTEND = new Date(event.DTEND);
        	return event;
        }

        function dateToday() {
        	return stripTime(new Date());
        }
        function dateTomorrow() {
        	var today = dateToday();
        	today.setDate(today.getDate() + 1);
        	return today;
        }

        function notBefore(date) {
        	return function(event) {
        		return event.DTSTART >= date;
        	}
        }

        function between(dateStart, dateEnd) {
        	return function(event) {
        		return event.dtstart >= dateStart && event.dstart < dateEnd;
        	}
        }

        function groupByDay(vevents) {
        	var days = {}
        	for(var i = 0; i < vevents.length; ++i) {
        		var event = vevents[i];
        		// We need a string to key our obj with
        		var dateKey = stripTime(event.DTSTART).toISOString();
        		if(!days[dateKey]) {
        			days[dateKey] = []
        		}
        		days[dateKey].push(new Event(event));
        	}
        	var sortedDays = [];
        	for(key in days) {
        		var events = days[key];
        		events.sort(function(a, b){
        			return a.vevent.DTSTART.milliseconds - b.vevent.DTSTART.milliseconds;
        		});
        		sortedDays.push([key, events]);
        	}
        	sortedDays.sort(function(a, b) {
        		if(a[0] < b[0])
        			return -1;
        		else if(a[0] > b[0])
        			return 1;
        		return 0;
        	});

        	return sortedDays;
        }

        function stripTime(date) {
        	return new Date(date.getFullYear(), date.getMonth(),
        			date.getDate());
        }

        /**
         * Loads widget saved state, calling the callback(success, data)
         * function once the state is loaded.
         */
        function getState(callback) {
        	sakai.api.Widgets.loadWidgetData(tuid, callback);
        }

        /////////////////////////
        // Main View functions //
        /////////////////////////

        /** Called when the calendar data has been updated. */
        function updateCalendar() {

        	var rendered = sakai.api.Util.TemplateRenderer("#agenda_template", {
				title: _title,
				days: _groupedDays
			});

        	$(".ajax-content", $rootel).html(rendered);
        	$(".ajax-content .summary.compact", $rootel).toggle(
        			expandCalendarEntry, contractCalendarEntry);
        	$(".loading", $rootel).hide();
        	$(".ajax-content", $rootel).show();
        }

        function buildTimeString(date) {
        	var hour = date.getHours();
        	var minute = "" + date.getMinutes();
        	if(minute.length === 1)
        		minute = "0" + minute;
        	return hour + ":" + minute;
        }

        // Length of one day in milliseconds
        var DAY_MILLIS = 1000*60*60*24;
        var MAX_DAYS_AGO = 5;

        function getDayDelta(from, to) {
        	// Millisecond time @ start of today
        	var fromms = stripTime(from).getTime();
        	var toms = stripTime(to).getTime();
        	// Calculate number of days between from and to.
        	return Math.floor((toms - fromms) / DAY_MILLIS);
        }

        /**
         * Builds a relative date string from an integer day delta. Day deltas
         * can be calculated by getDayDelta().
         *
         * For example:
         * buildRelativeDateString(0) => "Today"
         * buildRelativeDateString(-1) => "Yesterday"
         * buildRelativeDateString(1) => "Tomorrow"
         * buildRelativeDateString(-10) => "10 days ago"
         * buildRelativeDateString(10) => "In 10 days"
         */
        function buildRelativeDateString(delta) {
        	// make sure we have an integer
        	var days = Math.floor(delta);
        	if(days == 0)
				return "Today";
			else if(days == 1)
				return "Tomorrow";
			else if(days == -1)
				return "Yesterday";
			else if(days < 0)
				return "" + Math.abs(days) + " days ago";
			else
				return "In " + days + " days time";

        }

        function buildAbsoluteDateString(date) {
        	var dayName = DAYS[date.getDay()];
        	var dayNumber = date.getDate();
        	var monthName = MONTHS[date.getMonth()];
        	return dayName + " " + dayNumber + " " + monthName;
        }

        function expandCalendarEntry(jqevent) {
        	var summary = $(this);
        	var expanded = summary.siblings(".full");

        	summary.removeClass("compact expandable").addClass("contractable");
        	expanded.slideDown();
        }

        function contractCalendarEntry(jqevent) {
        	var summary = $(this);
        	var expanded = summary.siblings(".full");

        	summary.addClass("compact expandable").removeClass("contractable");
        	expanded.slideUp();
        }

        /////////////////////////////
        // Settings View functions //
        /////////////////////////////

        /**
         * Watch for value changes to the settings URL field in order to rewrite
         * webcal:// urls to http://.
         */
        settingsFormUrlField.change(function() {
        	var urltext = $(this).val();
        	// Help people inputting webcal:// links by rewriting them to http
        	urltext = urltext.replace(/^webcal:\/\//, "http://")
        	$(this).val(urltext);
        });

        function onWidgetSettingsStateAvailable(success, state) {
        	if(success) {
	        	settingsFormTitleField.val(state.title);
	        	settingsFormUrlField.val(state.url);
        	}
        	else {
        		alert("Error fetching saved settings");
        	}
        }

        /** Add listener to setting form submit */
        function settingsSave() {
        	var state = {
        			title: 	settingsFormTitleField.val(),
        			url: settingsFormUrlField.val()
        	};

        	// async save our widget's state
        	sakai.api.Widgets.saveWidgetData(tuid, state,
        			onWidgetSettingsDataSaved);
        }

        function onWidgetSettingsDataSaved(success, data) {
        	if (success) {
        		// Settings finished, switch to Main view
        		sakai.api.Widgets.Container.informFinish(tuid, "lecturelist");
        	} else {
        		sakai.api.Util.notification.show("Couldn't Save Your Settings",
        				"An error prevented your settings from being saved. "
        				+ " Please try again.",
        				sakai.api.Util.notification.type.ERROR);
        	}
        }

        /////////////////////////////
        // Initialisation function //
        /////////////////////////////

        /**
         * Initialization function DOCUMENTATION
         */
        var doInit = function () {
            console.log("lecturelist doInit()");

            if (showSettings) {

            	// Setup validation on settings form
            	var validateOpts = { submitHandler: settingsSave };
                sakai.api.Util.Forms.validate(settingsForm, validateOpts, true);

                // Async fetch widget settings to populate form
                getState(onWidgetSettingsStateAvailable);

                // show the Settings view
                $settingsContainer.show();
            } else {
            	// set up Main view

            	// Async fetch widget settings to populate form
                getState(onStateAvailable);

            	$mainContainer.show();
            	$(".loading", $rootel).fadeIn(1000);
            }
        };

        // run the initialization function when the widget object loads
        doInit();
    };

    // inform Sakai OAE that this widget has loaded and is ready to run
    sakai.api.Widgets.widgetLoader.informOnLoad("lecturelist");
});
<|endoftext|>


<commit_before>const fs       = require('fs')
const path     = require('path')
const {name}   = require('./package.json')
const requireg = require('requireg')

module.exports = (job, settings, { input, provider, params }, type) => {
    if (type != 'postrender') {
        throw new Error(`Action ${name} can be only run in postrender mode, you provided: ${type}.`)
    }

    if (!provider) {
        throw new Error(`Provider is missing.`)
    }

    /* check if input has been provided */
    input = input || job.output;

    /* fill absolute/relative paths */
    if (!path.isAbsolute(input)) input = path.join(job.workpath, input);

    settings.logger.log(`[${job.uid}] starting action-upload action`)

    try {
        return requireg('@nexrender/provider-' + provider).upload(job, settings, input, params || {});
    } catch (e) {
        if (e.message.indexOf('Could not require module') !== -1) {
            return Promise.reject(new Error(`Couldn\'t find module @nexrender/provider-${provider}, Unknown provider given.`))
        }

        throw e;
    }
}
<commit_msg>Enable globally installed custom upload action<commit_after>const fs       = require('fs')
const path     = require('path')
const {name}   = require('./package.json')
const requireg = require('requireg')

module.exports = (job, settings, { input, provider, params }, type) => {
    if (type != 'postrender') {
        throw new Error(`Action ${name} can be only run in postrender mode, you provided: ${type}.`)
    }

    if (!provider) {
        throw new Error(`Provider is missing.`)
    }

    /* check if input has been provided */
    input = input || job.output;

    /* fill absolute/relative paths */
    if (!path.isAbsolute(input)) input = path.join(job.workpath, input);

    settings.logger.log(`[${job.uid}] starting action-upload action`)

    let requirePackage = ''
    try {
        /* try requiring official providers */
        requirePackage = `@nexrender/provider-${provider}`
        return requireg('@nexrender/provider-' + provider).upload(job, settings, input, params || {});

    } catch (e) {
        if (e.message.indexOf('Could not require module') !== -1) {
            try{
                /* try requiring custom providers */
                requirePackage = provider
                return requireg(provider).upload(job, settings, input, params || {});

            } catch(e) {
                if (e.message.indexOf('Could not require module') !== -1) {
                    return Promise.reject(new Error(`Couldn\'t find module ${requirePackage}, Unknown provider given.`))
                }

                throw e;
            }
        }

        throw e;
    }
}
<|endoftext|>


<commit_before>"use strict";
let express = require("express");
let router = express.Router(); // eslint-disable-line new-cap
let groups = require("../helpers/groups");
let { db, as } = require("../helpers/db");
let { userByEmail } = require("../helpers/user");
let log = require("winston");

/**
 * @api {get} /bookmark/list/:userId List bookmarks for a given user
 * @apiGroup bookmarks
 * @apiVersion 0.1.0
 * @apiName getbookmarksforuser
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data user data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 * {
 *   status: "success",
 *   data: [
 *   {
 *   }
 * ],
 *   message: "Retrieved ALL bookmarks for a user"
 * }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

async function lookupBookmarksById(req, res, userId) {
  try {
    const data = await db.any("SELECT * FROM bookmarks WHERE userid=$1", [
      as.number(userId)
    ]);
    res.json({
      success: true,
      status: "success",
      data: data,
      message: "Retrieved ALL bookmarks for specified user"
    });
  } catch (error) {
    log.error(error);
    res.json({ success: false, error: error.message || error });
  }
}

async function queryBookmarks(req, res) {
  try {
    let userid = as.number(req.params.userid);

    if (!userid) {
      userid = req.user.user_id; // put there by preferUser
    }
    lookupBookmarksById(req, res, userid);
  } catch (error) {
    log.error(error);
    res.json({ success: false, error: error.message || error });
  }
}

router.get("/list", queryBookmarks);
router.get("/list/:userid", queryBookmarks);

/**
 * @api {post} /bookmark/add Create a bookmark
 * @apiGroup bookmarks
 * @apiVersion 0.1.0
 * @apiName addBookmark
 * @apiParam {String[]} bookmarkType Bookmark type (case,method, etc.)
 * @apiParam {Number} thingid ID of the thing (case ID, etc.)
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data user data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

router.post("/add", async function addBookmark(req, res) {
  try {
    if (!req.body.bookmarkType) {
      log.error("Required parameter (bookmarkType) wasn't specified");
      res.status(400).json({
        message: "Required parameter (bookmarkType) wasn't specified"
      });
      return;
    }
    if (!req.body.thingid) {
      log.error("Required parameter (thingid) wasn't specified");
      res
        .status(400)
        .json({ error: "Required parameter (thingid) wasn't specified" });
      return;
    }
    if (!req.user.id) {
      log.error("No user");
      res.status(400).json({ error: "You must be logged in to perform this action." });
      return;
    }
    let userId = as.number(req.user.id);
    let thingid = as.number(req.body.thingid);
    let bookmarkType = req.body.bookmarkType;
    const data1 = await db.oneOrNone(
      "select * from bookmarks where bookmarktype = ${bookmarkType} AND thingid = ${thingid} AND userid = ${userId}",
      { bookmarkType, thingid, userId }
    );
    if (data1) {
      return res.status(304).json({
        success: true,
        status: "success",
        data: data1.id,
        message: "bookmark already exists, no action"
      });
    }
    const data2 = await db.one(
      "insert into bookmarks(bookmarktype, thingid, userid) VALUES(${bookmarkType},${thingid},${userId}) returning id",
      { bookmarkType, thingid, userId }
    );
    res.status(201).json({
      success: true,
      status: "success",
      data: data2.id,
      message: "Inserted bookmark, returning ID"
    });
  } catch (error) {
    log.error("Exception in INSERT", error);
    res.status(500).json({
      success: false,
      error: error.message || error
    });
  }
});

/**
 * @api {delete} /bookmark Delete specified bookmark
 * @apiGroup bookmarks
 * @apiVersion 0.1.0
 * @apiName updateUser
 * @apiParam {String[]} bookmarkType Bookmark type (case,method, etc.)
 * @apiParam {Number} thingid ID of the thing (case ID, etc.)
 *
 * @apiSuccess {Boolean} OK true if call was successful
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

router.delete("/delete", async function updateUser(req, res) {
  try {
    const userId = as.number(req.user.id);
    const bookmarkType = req.body.bookmarkType;
    const thingid = as.number(req.body.thingid);
    const data1 = await db.one(
      "select * from bookmarks where bookmarktype = ${bookmarkType} AND thingid = ${thingid} AND userid = ${userId}",
      { bookmarkType, thingid, userId }
    );
    const data2 = await db.none(
      "delete from bookmarks where id = $1",
      data1.id
    );
    res.status(200).json({ status: "success", message: `Removed a bookmark` });
  } catch (error) {
    log.error("Error deleting bookmark", error);
    res.json({
      success: false,
      error: error.message || error
    });
  }
});

module.exports = router;
<commit_msg>return a 401 if the user is not logged in<commit_after>"use strict";
let express = require("express");
let router = express.Router(); // eslint-disable-line new-cap
let groups = require("../helpers/groups");
let { db, as } = require("../helpers/db");
let { userByEmail } = require("../helpers/user");
let log = require("winston");

/**
 * @api {get} /bookmark/list/:userId List bookmarks for a given user
 * @apiGroup bookmarks
 * @apiVersion 0.1.0
 * @apiName getbookmarksforuser
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data user data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 * {
 *   status: "success",
 *   data: [
 *   {
 *   }
 * ],
 *   message: "Retrieved ALL bookmarks for a user"
 * }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

async function lookupBookmarksById(req, res, userId) {
  try {
    const data = await db.any("SELECT * FROM bookmarks WHERE userid=$1", [
      as.number(userId)
    ]);
    res.json({
      success: true,
      status: "success",
      data: data,
      message: "Retrieved ALL bookmarks for specified user"
    });
  } catch (error) {
    log.error(error);
    res.json({ success: false, error: error.message || error });
  }
}

async function queryBookmarks(req, res) {
  try {
    let userid = as.number(req.params.userid);

    if (!userid) {
      userid = req.user.user_id; // put there by preferUser
    }
    lookupBookmarksById(req, res, userid);
  } catch (error) {
    log.error(error);
    res.json({ success: false, error: error.message || error });
  }
}

router.get("/list", queryBookmarks);
router.get("/list/:userid", queryBookmarks);

/**
 * @api {post} /bookmark/add Create a bookmark
 * @apiGroup bookmarks
 * @apiVersion 0.1.0
 * @apiName addBookmark
 * @apiParam {String[]} bookmarkType Bookmark type (case,method, etc.)
 * @apiParam {Number} thingid ID of the thing (case ID, etc.)
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 * @apiSuccess {Object} data user data
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

router.post("/add", async function addBookmark(req, res) {
  try {
    if (!req.body.bookmarkType) {
      log.error("Required parameter (bookmarkType) wasn't specified");
      res.status(400).json({
        message: "Required parameter (bookmarkType) wasn't specified"
      });
      return;
    }
    if (!req.body.thingid) {
      log.error("Required parameter (thingid) wasn't specified");
      res
        .status(400)
        .json({ error: "Required parameter (thingid) wasn't specified" });
      return;
    }
    if (!req.user.id) {
      log.error("No user");
      res.status(401).json({ error: "You must be logged in to perform this action." });
      return;
    }
    let userId = as.number(req.user.id);
    let thingid = as.number(req.body.thingid);
    let bookmarkType = req.body.bookmarkType;
    const data1 = await db.oneOrNone(
      "select * from bookmarks where bookmarktype = ${bookmarkType} AND thingid = ${thingid} AND userid = ${userId}",
      { bookmarkType, thingid, userId }
    );
    if (data1) {
      return res.status(304).json({
        success: true,
        status: "success",
        data: data1.id,
        message: "bookmark already exists, no action"
      });
    }
    const data2 = await db.one(
      "insert into bookmarks(bookmarktype, thingid, userid) VALUES(${bookmarkType},${thingid},${userId}) returning id",
      { bookmarkType, thingid, userId }
    );
    res.status(201).json({
      success: true,
      status: "success",
      data: data2.id,
      message: "Inserted bookmark, returning ID"
    });
  } catch (error) {
    log.error("Exception in INSERT", error);
    res.status(500).json({
      success: false,
      error: error.message || error
    });
  }
});

/**
 * @api {delete} /bookmark Delete specified bookmark
 * @apiGroup bookmarks
 * @apiVersion 0.1.0
 * @apiName updateUser
 * @apiParam {String[]} bookmarkType Bookmark type (case,method, etc.)
 * @apiParam {Number} thingid ID of the thing (case ID, etc.)
 *
 * @apiSuccess {Boolean} OK true if call was successful
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "OK": true,
 *       "data": {
 *         "ID": 3,
 *         "Description": 'foo'
 *        }
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

router.delete("/delete", async function updateUser(req, res) {
  try {
    const userId = as.number(req.user.id);
    const bookmarkType = req.body.bookmarkType;
    const thingid = as.number(req.body.thingid);
    const data1 = await db.one(
      "select * from bookmarks where bookmarktype = ${bookmarkType} AND thingid = ${thingid} AND userid = ${userId}",
      { bookmarkType, thingid, userId }
    );
    const data2 = await db.none(
      "delete from bookmarks where id = $1",
      data1.id
    );
    res.status(200).json({ status: "success", message: `Removed a bookmark` });
  } catch (error) {
    log.error("Error deleting bookmark", error);
    res.json({
      success: false,
      error: error.message || error
    });
  }
});

module.exports = router;
<|endoftext|>


<commit_before>const core = require('@actions/core');
const github = require('@actions/github');

function getText() {
    // Attempt to find the text to replace. This is somewhat involved since we trigger on many actions.
    const event = github.context.eventName;

    if (event === 'issues') {
        return github.context.payload.issue.body;
    }
    else if (event === 'issue_comment') {
        return github.context.payload.comment.body;
    }
    else if (event === 'pull_request') {
        return github.context.payload.pull_request.body;
    }
    else if (event === 'pull_request_review') {
        return github.context.payload.review.body;
    }
    else if (event === 'pull_request_review_comment') {
        return github.context.payload.comment.body;
    }

    return null;
}

async function setText(token, replacement) {
    const client = github.getOctokit(token);

    const event = github.context.eventName;

    if (event === 'issues') {
        await client.issues.update({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            issue_number: github.context.payload.issue.number,
            body: replacement,
        });
    }
    else if (event === 'issue_comment') {
        await client.issues.updateComment({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            comment_id: github.context.payload.comment.id,
            body: replacement,
        });
    }
    else if (event === 'pull_request') {
        await client.pulls.update({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            pull_number: github.context.payload.pull_request.number,
            body: replacement,
        });
    }
    else if (event === 'pull_request_review') {
        await client.pulls.updateReview({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            pull_number: github.context.payload.pull_request.number,
            review_id: github.context.payload.review.id,
            body: replacement,
        });
    }
    else if (event === 'pull_request_review_comment') {
        await client.pulls.updateReviewComment({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            comment_id: github.context.payload.comment.id,
            body: replacement,
        });
    }
}

try {
    const prefix = core.getInput('issue-prefix');
    const baseUrl = core.getInput('youtrack-base-url');
    const token = core.getInput('repo-token');

    const text = getText();
    if (text === null || text === undefined) {
        return;
    }

    const regex = new RegExp(`(?<!\\[)\\b(${prefix}-\\d+)\\b(?!\\])`, 'g');

    if (!regex.test(text)) {
        // Exit early when no links need to be inserted to avoid API calls
        return
    }

    const replacement = text.replace(regex, `[$1](${baseUrl}/issue/$1)`);

    setText(token, replacement);
}
catch (e) {
    core.setFailed(e.message);
}
<commit_msg>Fix regex issue for YouTrack issue link github integration<commit_after>const core = require('@actions/core');
const github = require('@actions/github');

function getText() {
    // Attempt to find the text to replace. This is somewhat involved since we trigger on many actions.
    const event = github.context.eventName;

    if (event === 'issues') {
        return github.context.payload.issue.body;
    }
    else if (event === 'issue_comment') {
        return github.context.payload.comment.body;
    }
    else if (event === 'pull_request') {
        return github.context.payload.pull_request.body;
    }
    else if (event === 'pull_request_review') {
        return github.context.payload.review.body;
    }
    else if (event === 'pull_request_review_comment') {
        return github.context.payload.comment.body;
    }

    return null;
}

async function setText(token, replacement) {
    const client = github.getOctokit(token);

    const event = github.context.eventName;

    if (event === 'issues') {
        await client.issues.update({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            issue_number: github.context.payload.issue.number,
            body: replacement,
        });
    }
    else if (event === 'issue_comment') {
        await client.issues.updateComment({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            comment_id: github.context.payload.comment.id,
            body: replacement,
        });
    }
    else if (event === 'pull_request') {
        await client.pulls.update({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            pull_number: github.context.payload.pull_request.number,
            body: replacement,
        });
    }
    else if (event === 'pull_request_review') {
        await client.pulls.updateReview({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            pull_number: github.context.payload.pull_request.number,
            review_id: github.context.payload.review.id,
            body: replacement,
        });
    }
    else if (event === 'pull_request_review_comment') {
        await client.pulls.updateReviewComment({
            owner: github.context.repo.owner,
            repo: github.context.repo.repo,
            comment_id: github.context.payload.comment.id,
            body: replacement,
        });
    }
}

try {
    const prefix = core.getInput('issue-prefix');
    const baseUrl = core.getInput('youtrack-base-url');
    const token = core.getInput('repo-token');

    const text = getText();
    if (text === null || text === undefined) {
        return;
    }

    const regex = new RegExp(`(?<!\\[|\/issue\/)\\b(${prefix}-\\d+)\\b(?!\\])`, 'g');

    if (!regex.test(text)) {
        // Exit early when no links need to be inserted to avoid API calls
        return
    }

    const replacement = text.replace(regex, `[$1](${baseUrl}/issue/$1)`);

    setText(token, replacement);
}
catch (e) {
    core.setFailed(e.message);
}
<|endoftext|>


<commit_before>/**
 * sessionAuth
 *
 * @module      :: Policy
 * @description :: Simple policy to allow any authenticated user
 *                 Assumes that your login action in one of your controllers sets `req.session.authenticated = true;`
 * @docs        :: http://sailsjs.org/#!documentation/policies
 *
 */
module.exports = function(req, res, next) {

  // User is allowed, proceed to the next policy,
  // or if this is the last policy, the controller
  if (req.session.authenticated) {
    next();
  } else {
    var playSession = new PlaySession(req);
    if (playSession.isValid()) {
      playSession.fetchUser().then(function(user) {
        if (user) {
          sails.log.debug("policy: sessionAuth: validated as " + user.get('email'));
          req.session.authenticated = true;
          req.session.userId = user.id;

          req.rollbar_person = user.pick('id', 'name', 'email');
        }
        next();
      });
    } else {
      // User is not allowed
      // (default res.forbidden() behavior can be overridden in `config/403.js`)
      sails.log.debug("policy: sessionAuth: fail");
      res.forbidden();
    }
  }
};
<commit_msg>make transition to new play session handling seamless<commit_after>/**
 * sessionAuth
 *
 * @module      :: Policy
 * @description :: Simple policy to allow any authenticated user
 *                 Assumes that your login action in one of your controllers sets `req.session.authenticated = true;`
 * @docs        :: http://sailsjs.org/#!documentation/policies
 *
 */
module.exports = function(req, res, next) {

  // User is allowed, proceed to the next policy,
  // or if this is the last policy, the controller
  if (req.session.authenticated && req.session.userId) {
    next();
  } else {
    var playSession = new PlaySession(req);
    if (playSession.isValid()) {
      playSession.fetchUser().then(function(user) {
        if (user) {
          sails.log.debug("policy: sessionAuth: validated as " + user.get('email'));
          req.session.authenticated = true;
          req.session.userId = user.id;

          req.rollbar_person = user.pick('id', 'name', 'email');
        }
        next();
      });
    } else {
      // User is not allowed
      // (default res.forbidden() behavior can be overridden in `config/403.js`)
      sails.log.debug("policy: sessionAuth: fail");
      res.forbidden();
    }
  }
};
<|endoftext|>


<commit_before>const fs = require('fs');
const test = require('tape');
const path = require('path');
const load = require('load-json-file');
const write = require('write-json-file');
const truncate = require('@turf/truncate');
const {point, lineString, geometryCollection, featureCollection} = require('@turf/helpers');
const translate = require('./');

const directories = {
    in: path.join(__dirname, 'test', 'in') + path.sep,
    out: path.join(__dirname, 'test', 'out') + path.sep
};

const fixtures = fs.readdirSync(directories.in).map(filename => {
    return {
        filename,
        name: path.parse(filename).name,
        geojson: load.sync(directories.in + filename)
    };
});

test('translate', t => {
    for (const {filename, name, geojson} of fixtures) {
        let {distance, direction, units, zTranslation} = geojson.properties || {};

        const translated = translate(geojson, distance, direction, units, zTranslation);
        const result = featureCollection([colorize(truncate(translated, 6, 3)), geojson]);

        if (process.env.REGEN) write.sync(directories.out + filename, result);
        t.deepEqual(result, load.sync(directories.out + filename), name);
    }

    t.end();
});

test('translate -- throws', t => {
    const pt = point([-70.823364, -33.553984]);

    t.throws(() => translate(null, 100, -29), 'missing geojson');
    t.throws(() => translate(pt, null, 98), 'missing distance');
    t.throws(() => translate(pt, 23, null), 'missing direction');
    t.throws(() => translate(pt, 56, 57, 'notAunit'), 'invalid units');
    t.throws(() => translate(pt, 56, 57, 'miles', 'zTrans'), 'invalid zTranslation');

    t.end();
});

test('rotate -- mutated input', t => {
    const line = lineString([[10, 10], [12, 15]]);
    const lineBefore = JSON.parse(JSON.stringify(line));

    translate(line, 100, 50);
    t.deepEqual(line, lineBefore, 'input should NOT be mutated');

    translate(line, 100, 50, 'kilometers', undefined, true);
    t.deepEqual(truncate(line, 1), lineString([[10.7, 10.6], [12.7, 15.6]]), 'input should be mutated');
    t.end();
});

test('rotate -- geometry support', t => {
    const line = lineString([[10, 10], [12, 15]]);
    t.assert(translate(geometryCollection([line.geometry]), 100, 50), 'geometryCollection support');
    t.assert(translate(geometryCollection([line.geometry]).geometry, 100, 50), 'geometryCollection support');
    t.assert(translate(featureCollection([line]), 100, 50), 'featureCollection support');
    t.assert(translate(line.geometry, 100, 50), 'geometry line support');
    t.assert(translate(line.geometry, 100, 50), 'geometry pt support');
    t.assert(translate(line, 0, 100), 'shortcut no-motion');
    t.skip('pt coordinate support');
    t.end();
});

// style result
function colorize(geojson) {
    if (geojson.geometry.type === 'Point' || geojson.geometry.type === 'MultiPoint') {
        geojson.properties['marker-color'] = '#F00';
        geojson.properties['marker-symbol'] = 'star';
    } else {
        geojson.properties['stroke'] = '#F00';
        geojson.properties['stroke-width'] = 4;
    }
    return geojson;
}
<commit_msg>Remove skipped test turf-translate<commit_after>const fs = require('fs');
const test = require('tape');
const path = require('path');
const load = require('load-json-file');
const write = require('write-json-file');
const truncate = require('@turf/truncate');
const {point, lineString, geometryCollection, featureCollection} = require('@turf/helpers');
const translate = require('./');

const directories = {
    in: path.join(__dirname, 'test', 'in') + path.sep,
    out: path.join(__dirname, 'test', 'out') + path.sep
};

const fixtures = fs.readdirSync(directories.in).map(filename => {
    return {
        filename,
        name: path.parse(filename).name,
        geojson: load.sync(directories.in + filename)
    };
});

test('translate', t => {
    for (const {filename, name, geojson} of fixtures) {
        let {distance, direction, units, zTranslation} = geojson.properties || {};

        const translated = translate(geojson, distance, direction, units, zTranslation);
        const result = featureCollection([colorize(truncate(translated, 6, 3)), geojson]);

        if (process.env.REGEN) write.sync(directories.out + filename, result);
        t.deepEqual(result, load.sync(directories.out + filename), name);
    }

    t.end();
});

test('translate -- throws', t => {
    const pt = point([-70.823364, -33.553984]);

    t.throws(() => translate(null, 100, -29), 'missing geojson');
    t.throws(() => translate(pt, null, 98), 'missing distance');
    t.throws(() => translate(pt, 23, null), 'missing direction');
    t.throws(() => translate(pt, 56, 57, 'notAunit'), 'invalid units');
    t.throws(() => translate(pt, 56, 57, 'miles', 'zTrans'), 'invalid zTranslation');

    t.end();
});

test('rotate -- mutated input', t => {
    const line = lineString([[10, 10], [12, 15]]);
    const lineBefore = JSON.parse(JSON.stringify(line));

    translate(line, 100, 50);
    t.deepEqual(line, lineBefore, 'input should NOT be mutated');

    translate(line, 100, 50, 'kilometers', undefined, true);
    t.deepEqual(truncate(line, 1), lineString([[10.7, 10.6], [12.7, 15.6]]), 'input should be mutated');
    t.end();
});

test('rotate -- geometry support', t => {
    const line = lineString([[10, 10], [12, 15]]);
    t.assert(translate(geometryCollection([line.geometry]), 100, 50), 'geometryCollection support');
    t.assert(translate(geometryCollection([line.geometry]).geometry, 100, 50), 'geometryCollection support');
    t.assert(translate(featureCollection([line]), 100, 50), 'featureCollection support');
    t.assert(translate(line.geometry, 100, 50), 'geometry line support');
    t.assert(translate(line.geometry, 100, 50), 'geometry pt support');
    t.assert(translate(line, 0, 100), 'shortcut no-motion');
    t.end();
});

// style result
function colorize(geojson) {
    if (geojson.geometry.type === 'Point' || geojson.geometry.type === 'MultiPoint') {
        geojson.properties['marker-color'] = '#F00';
        geojson.properties['marker-symbol'] = 'star';
    } else {
        geojson.properties['stroke'] = '#F00';
        geojson.properties['stroke-width'] = 4;
    }
    return geojson;
}
<|endoftext|>


<commit_before>/**
 * Copyright 2013 IBM Corp.
 *
 * 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.
 **/

var RED = require(process.env.NODE_RED_HOME+"/red/red");
var settings = RED.settings;
var util = require("util");
var fs = require('fs');
var plat = require('os').platform();
var pre = "\\\\.\\";

if (! plat.match(/^win/)) {
    util.log("[26-rawserial.js] Advise: Only really needed for Windows boxes without serialport npm module installed.");
    pre = "";
}

function RawSerialInNode(n) {
    RED.nodes.createNode(this,n);
    this.port = n.port;
    this.split = n.split||null;
    if (this.split == '\\n') this.split = "\n";
    if (this.split == '\\r') this.split = "\r";
    var node = this;

    var setupSerial = function() {
        node.inp = fs.createReadStream(pre+node.port);
        node.log("opened "+pre+node.port);
        node.inp.setEncoding('utf8');
        var line = "";
        node.inp.on('data', function (data) {
            if (node.split != null) {
                if (data == node.split) {
                    node.send({payload:line});
                    line = "";
                }
                else { line += data; }
            }
            else { node.send({payload:data}); }
        });
        //node.inp.on('end', function (error) {console.log("End", error);});
        node.inp.on('close', function (error) {
            util.log("[rawserial] "+node.port+" closed");
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
        node.inp.on('error', function(error) {
            if (error.code == "ENOENT") { util.log("[rawserial] port "+node.port+" not found"); }
            else { util.log("[rawserial] "+node.port+" error "+error); }
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
    }
    setupSerial();

    node.on('close', function() {
        if (node.tout) { clearTimeout(node.tout); }
        if (node.inp) { node.inp.pause(); }
    });

}
RED.nodes.registerType("rawserial in",RawSerialInNode);

function RawSerialOutNode(n) {
    RED.nodes.createNode(this,n);
    this.port = n.port;
    var node = this;

    var setupSerial = function() {
        node.oup = fs.createWriteStream(pre+node.port,{ flags:'w', encoding:'utf8', mode:0666 });
        node.on("input", function(msg) {
            if (msg.payload != null) {
                node.oup.write(msg.payload);
            }
        });
        node.oup.on('open', function (error) { util.log("[rawserial] opened "+node.port); });
        node.oup.on('end', function (error) { console.log("End",error); });
        node.oup.on('close', function (error) {
            util.log("[rawserial] "+node.port+" closed");
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
        node.oup.on('error', function(error) {
            if (error.code == "EACCES") { util.log("[rawserial] can't access port "+node.port); }
            else if (error.code == "EIO") { util.log("[rawserial] can't write to port "+node.port); }
            else { util.log("[rawserial] "+node.port+" error "+error); }
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
    }
    setupSerial();

    node.on('close', function() {
        if (node.tout) { clearTimeout(node.tout); }
    });
}
RED.nodes.registerType("rawserial out",RawSerialOutNode);
<commit_msg>Rawserial node - change advis/ce to info.<commit_after>/**
 * Copyright 2013 IBM Corp.
 *
 * 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.
 **/

var RED = require(process.env.NODE_RED_HOME+"/red/red");
var settings = RED.settings;
var util = require("util");
var fs = require('fs');
var plat = require('os').platform();
var pre = "\\\\.\\";

if (!plat.match(/^win/)) {
    util.log("[26-rawserial.js] Info : only really needed for Windows boxes without serialport npm module installed.");
    pre = "";
}

function RawSerialInNode(n) {
    RED.nodes.createNode(this,n);
    this.port = n.port;
    this.split = n.split||null;
    if (this.split == '\\n') this.split = "\n";
    if (this.split == '\\r') this.split = "\r";
    var node = this;

    var setupSerial = function() {
        node.inp = fs.createReadStream(pre+node.port);
        node.log("opened "+pre+node.port);
        node.inp.setEncoding('utf8');
        var line = "";
        node.inp.on('data', function (data) {
            if (node.split != null) {
                if (data == node.split) {
                    node.send({payload:line});
                    line = "";
                }
                else { line += data; }
            }
            else { node.send({payload:data}); }
        });
        //node.inp.on('end', function (error) {console.log("End", error);});
        node.inp.on('close', function (error) {
            util.log("[rawserial] "+node.port+" closed");
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
        node.inp.on('error', function(error) {
            if (error.code == "ENOENT") { util.log("[rawserial] port "+node.port+" not found"); }
            else { util.log("[rawserial] "+node.port+" error "+error); }
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
    }
    setupSerial();

    node.on('close', function() {
        if (node.tout) { clearTimeout(node.tout); }
        if (node.inp) { node.inp.pause(); }
    });

}
RED.nodes.registerType("rawserial in",RawSerialInNode);

function RawSerialOutNode(n) {
    RED.nodes.createNode(this,n);
    this.port = n.port;
    var node = this;

    var setupSerial = function() {
        node.oup = fs.createWriteStream(pre+node.port,{ flags:'w', encoding:'utf8', mode:0666 });
        node.on("input", function(msg) {
            if (msg.payload != null) {
                node.oup.write(msg.payload);
            }
        });
        node.oup.on('open', function (error) { util.log("[rawserial] opened "+node.port); });
        node.oup.on('end', function (error) { console.log("End",error); });
        node.oup.on('close', function (error) {
            util.log("[rawserial] "+node.port+" closed");
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
        node.oup.on('error', function(error) {
            if (error.code == "EACCES") { util.log("[rawserial] can't access port "+node.port); }
            else if (error.code == "EIO") { util.log("[rawserial] can't write to port "+node.port); }
            else { util.log("[rawserial] "+node.port+" error "+error); }
            node.tout = setTimeout(function() {
                setupSerial();
            },settings.serialReconnectTime);
        });
    }
    setupSerial();

    node.on('close', function() {
        if (node.tout) { clearTimeout(node.tout); }
    });
}
RED.nodes.registerType("rawserial out",RawSerialOutNode);
<|endoftext|>


<commit_before>//@flow
import { Cancelable } from 'models';
import { v4 as uuid } from 'uuid';

export class CancelablePromise<T> implements Cancelable<T> {
    #id : string;
    #cancel : () => void;
    #promise : Promise<T>;

    get id() { return this.#id; }
    get promise() : Promise<T> { return this.#promise; }

    cancel() {
        const cancelFunc = this.#cancel;
        cancelFunc();
    }

    map<TNew>(mapper : (val : T) => TNew) : Cancelable<TNew> {
        const mappedPromise = this.#promise.then(mapper);
        return new CancelablePromise(this.#promise.then(mapper), this.#cancel, this.#id);
    }

    constructor(promise : Promise<T>, cancelFunc : () => void, id? : string) {
        this.#promise = promise;
        this.#cancel = cancelFunc;
        this.#id = id || uuid();
    }
}

<commit_msg>Trivial - Remove redundant .then()<commit_after>//@flow
import { Cancelable } from 'models';
import { v4 as uuid } from 'uuid';

export class CancelablePromise<T> implements Cancelable<T> {
    #id : string;
    #cancel : () => void;
    #promise : Promise<T>;

    get id() { return this.#id; }
    get promise() : Promise<T> { return this.#promise; }

    cancel() {
        const cancelFunc = this.#cancel;
        cancelFunc();
    }

    map<TNew>(mapper : (val : T) => TNew) : Cancelable<TNew> {
        const mappedPromise = this.#promise.then(mapper);
        return new CancelablePromise(mappedPromise, this.#cancel, this.#id);
    }

    constructor(promise : Promise<T>, cancelFunc : () => void, id? : string) {
        this.#promise = promise;
        this.#cancel = cancelFunc;
        this.#id = id || uuid();
    }
}

<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('foundation.accordion', [])
    .controller('ZfAccordionController', zfAccordionController)
    .directive('zfAccordion', zfAccordion)
    .directive('zfAccordionItem', zfAccordionItem)
  ;

  zfAccordionController.$inject = ['$scope'];

  function zfAccordionController($scope) {
    var controller = this;
    var sections = controller.sections = $scope.sections = [];
    var multiOpen = controller.multiOpen = $scope.multiOpen = $scope.multiOpen || false;
    var collapsible = controller.collapsible = $scope.collapsible = $scope.multiOpen || $scope.collapsible || true; //multi open infers a collapsible true
    var autoOpen = controller.autoOpen = $scope.autoOpen = $scope.autoOpen || true; //auto open opens first tab on render

    controller.select = function(selectSection) {
      sections.forEach(function(section) {
        //if multi open is allowed, toggle a tab
        if(controller.multiOpen) {
          if(section.scope === selectSection) {
            section.scope.active = !section.scope.active;
          }
        } else {
          //non  multi open will close all tabs and open one
          section.scope.active = false;
          if(section.scope === selectSection) {
            //if collapsible is allowed, a tab will toggle
            section.scope.active = collapsible === true ? !section.scope.active : true;
          }
        }

      });
    };

    controller.addSection = function addsection(sectionScope) {
      sections.push({ scope: sectionScope });

      if(sections.length === 1 && autoOpen === true) {
        sections[0].active = true;
        sections[0].scope.active = true;
      }
    };

    controller.closeAll = function() {
      sections.forEach(function(section) {
        section.scope.active = false;
      });
    };
  }

  function zfAccordion() {
    var directive = {
      restrict: 'EA',
      transclude: 'true',
      replace: true,
      templateUrl: 'components/accordion/accordion.html',
      controller: 'ZfAccordionController',
      scope: {
        multiOpen: '@?',
        collapsible: '@?',
        autoOpen: '@?'
      },
      link: link
    };

    return directive;

    function link(scope, element, attrs, controller) {
      scope.multiOpen = controller.multiOpen = scope.multiOpen === "true" ? true : false;
      scope.collapsible = controller.collapsible = scope.collapsible === "true" ? true : false;
      scope.autoOpen = controller.autoOpen = scope.autoOpen === "true" ? true : false;
    }
  }

  //accordion item
  function zfAccordionItem() {
    var directive = {
        restrict: 'EA',
        templateUrl: 'components/accordion/accordion-item.html',
        transclude: true,
        scope: {
          title: '@'
        },
        require: '^zfAccordion',
        replace: true,
        controller: function() {},
        link: link
    };

    return directive;

    function link(scope, element, attrs, controller, transclude) {
      scope.active = false;
      controller.addSection(scope);

      scope.activate = function() {
        controller.select(scope);
      };

    }
  }

})();
<commit_msg>Fixed collapsible issue in accordion<commit_after>(function() {
  'use strict';

  angular.module('foundation.accordion', [])
    .controller('ZfAccordionController', zfAccordionController)
    .directive('zfAccordion', zfAccordion)
    .directive('zfAccordionItem', zfAccordionItem)
  ;

  zfAccordionController.$inject = ['$scope'];

  function zfAccordionController($scope) {
    var controller = this;
    var sections = controller.sections = $scope.sections = [];
    var multiOpen = controller.multiOpen = $scope.multiOpen = $scope.multiOpen || false;
    var collapsible = controller.collapsible = $scope.collapsible = $scope.multiOpen || $scope.collapsible || true; //multi open infers a collapsible true
    var autoOpen = controller.autoOpen = $scope.autoOpen = $scope.autoOpen || true; //auto open opens first tab on render

    controller.select = function(selectSection) {
      sections.forEach(function(section) {
        //if multi open is allowed, toggle a tab
        if(controller.multiOpen) {
          if(section.scope === selectSection) {
            section.scope.active = !section.scope.active;
          }
        } else {
          //non  multi open will close all tabs and open one
          if(section.scope === selectSection) {
            //if collapsible is allowed, a tab will toggle
            section.scope.active = collapsible ? !section.scope.active : true;
          } else {
            section.scope.active = false;
          }
        }

      });
    };

    controller.addSection = function addsection(sectionScope) {
      sections.push({ scope: sectionScope });

      if(sections.length === 1 && autoOpen === true) {
        sections[0].active = true;
        sections[0].scope.active = true;
      }
    };

    controller.closeAll = function() {
      sections.forEach(function(section) {
        section.scope.active = false;
      });
    };
  }

  function zfAccordion() {
    var directive = {
      restrict: 'EA',
      transclude: 'true',
      replace: true,
      templateUrl: 'components/accordion/accordion.html',
      controller: 'ZfAccordionController',
      scope: {
        multiOpen: '@?',
        collapsible: '@?',
        autoOpen: '@?'
      },
      link: link
    };

    return directive;

    function link(scope, element, attrs, controller) {
      scope.multiOpen = controller.multiOpen = scope.multiOpen === "true" ? true : false;
      scope.collapsible = controller.collapsible = scope.collapsible === "true" ? true : false;
      scope.autoOpen = controller.autoOpen = scope.autoOpen === "true" ? true : false;
    }
  }

  //accordion item
  function zfAccordionItem() {
    var directive = {
        restrict: 'EA',
        templateUrl: 'components/accordion/accordion-item.html',
        transclude: true,
        scope: {
          title: '@'
        },
        require: '^zfAccordion',
        replace: true,
        controller: function() {},
        link: link
    };

    return directive;

    function link(scope, element, attrs, controller, transclude) {
      scope.active = false;
      controller.addSection(scope);

      scope.activate = function() {
        controller.select(scope);
      };

    }
  }

})();
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */
CLASS({
  package: 'com.google.ymp.dao',
  name: 'MarketSubAuthorizer',
  implements: ['foam.dao.Authorizer'],

  requires: [
    'com.google.ymp.Market',
    'com.google.ymp.Person',
    'com.google.ymp.bb.Post',
  ],

  imports: [
    'personDAO_ as personDAO',
    'console',
  ],

  documentation: function() {/*
    <p>$$DOC{ref:'foam.dao.Authorizer'} that looks up the principal Person,
    checks for subscription to the given MarketID/p>
  */},

  properties: [
    {
      type: 'Array',
      subType: 'Property',
      name: 'marketProps',
      lazyFactory: function() {
        return this.Post.MARKET;
      },
    },
    {
      name: 'junctionMLang',
      documentation: 'The MLang operation for joining market property checks',
      lazyFactory: function() {
        return AND;
      },
    },
  ],

  methods: [
    function massageForPut(ret, X, old, nu) {
      ret(nu);
    },
    function massageForRead(ret, X, obj) {
      if ( ! X.principal ) {
        ret(null);
        return;
      }

      // lookup principal Person
      var self = this;
      this.personDAO.find(X.principal, {
        put: function(p) {
          // Construct query:
          // Join together from i = 0 to n - 1:
          //   Elem of person's subscribedMarkets = obj's marketProps[i] value.
          // Join for AND starts with TRUE.
          // Join for OR, IN, etc. starts with FALSE.
          var expr = this.junctionMLange === AND ? TRUE : FALSE;
          for ( var i = 0; i < this.marketProps.length; ++i ) {
            expr = this.junctionMLang(
                EQ(
                    self.Person.SUBSCRIBED_MARKETS,
                    this.marketProps[i].f(obj)),
                expr);
          }
          if ( expr.f(p) ) {
            ret(obj); // the principal is subscribed to the market this object belongs to
          } else {
            ret(null); // not subscribed, don't sync this object
          }
        },
        error: function(err) {
          self.console.warn('MarketSubAuthorizer user find error: ' + err, X.principal);
          ret(null);
        }
      });
    },
    function shouldAllowRemove(ret, X, obj) {
      if ( ! X.principal ) {
        ret(null);
        return;
      }

      ret(true);
    },
    function decorateForSelect(ret, X, dao) {
      if ( ! X.principal ) {
        ret(dao.where(FALSE));
        return;
      }
      var self = this;
      this.personDAO.find(X.principal, {
        put: function(p) {
          // filter by user's subscribed markets
          // HACK: Post.MARKET used to represent any model with a 'market' reference property
          ret(dao.where(IN(self.Post.MARKET, p.subscribedMarkets)));
        },
        error: function(err) {
          self.console.warn('MarketSubAuthorizer user select error: ' + err, X.principal);
          ret(dao.where(FALSE));
        }
      });
    },
  ]
});
<commit_msg>YMp: Fix this/self bug in MarketSubAuthorizer<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */
CLASS({
  package: 'com.google.ymp.dao',
  name: 'MarketSubAuthorizer',
  implements: ['foam.dao.Authorizer'],

  requires: [
    'com.google.ymp.Market',
    'com.google.ymp.Person',
    'com.google.ymp.bb.Post',
  ],

  imports: [
    'personDAO_ as personDAO',
    'console',
  ],

  documentation: function() {/*
    <p>$$DOC{ref:'foam.dao.Authorizer'} that looks up the principal Person,
    checks for subscription to the given MarketID/p>
  */},

  properties: [
    {
      type: 'Array',
      subType: 'Property',
      name: 'marketProps',
      lazyFactory: function() {
        return [this.Post.MARKET];
      },
    },
    {
      name: 'junctionMLang',
      documentation: 'The MLang operation for joining market property checks',
      lazyFactory: function() {
        return AND;
      },
    },
  ],

  methods: [
    function massageForPut(ret, X, old, nu) {
      ret(nu);
    },
    function massageForRead(ret, X, obj) {
      if ( ! X.principal ) {
        ret(null);
        return;
      }

      // lookup principal Person
      var self = this;
      self.personDAO.find(X.principal, {
        put: function(p) {
          // Construct query:
          // Join together from i = 0 to n - 1:
          //   Elem of person's subscribedMarkets = obj's marketProps[i] value.
          // Join for AND starts with TRUE.
          // Join for OR, IN, etc. starts with FALSE.
          var expr = self.junctionMLange === AND ? TRUE : FALSE;
          for ( var i = 0; i < self.marketProps.length; ++i ) {
            expr = self.junctionMLang(
                EQ(
                    self.Person.SUBSCRIBED_MARKETS,
                    self.marketProps[i].f(obj)),
                expr);
          }
          if ( expr.f(p) ) {
            ret(obj); // the principal is subscribed to the market this object belongs to
          } else {
            ret(null); // not subscribed, don't sync this object
          }
        },
        error: function(err) {
          self.console.warn('MarketSubAuthorizer user find error: ' + err, X.principal);
          ret(null);
        }
      });
    },
    function shouldAllowRemove(ret, X, obj) {
      if ( ! X.principal ) {
        ret(null);
        return;
      }

      ret(true);
    },
    function decorateForSelect(ret, X, dao) {
      if ( ! X.principal ) {
        ret(dao.where(FALSE));
        return;
      }
      var self = this;
      this.personDAO.find(X.principal, {
        put: function(p) {
          // filter by user's subscribed markets
          // HACK: Post.MARKET used to represent any model with a 'market' reference property
          ret(dao.where(IN(self.Post.MARKET, p.subscribedMarkets)));
        },
        error: function(err) {
          self.console.warn('MarketSubAuthorizer user select error: ' + err, X.principal);
          ret(dao.where(FALSE));
        }
      });
    },
  ]
});
<|endoftext|>


<commit_before>'use strict';

var os = require('os');
var spawn = require('child_process').spawn;
var path = require('path');

process.chdir(path.normalize(process.cwd() + '/engines/'));

if (os.platform() === 'linux') {
    var command = spawn('chmod', ['+x', path.normalize(__dirname + '/stockfish/stockfish-linux')]);
} else if (os.platform() === 'win32') {
    //Do nothing
} if (os.platform() === 'darwin') {
    //TODO:Test on Mac
}

command.on('error', function (error) {
        console.log(error);
});
<commit_msg>Fixed exception in makeExecutable.js in windows<commit_after>'use strict';

var os = require('os');
var spawn = require('child_process').spawn;
var path = require('path');

process.chdir(path.normalize(process.cwd() + '/engines/'));

if (os.platform() === 'linux') {
    var command = spawn('chmod', ['+x', path.normalize(__dirname + '/stockfish/stockfish-linux')]);
    command.on('error', function (error) {
        console.log(error);
    });
} else if (os.platform() === 'win32') {
    //Do nothing
} if (os.platform() === 'darwin') {
    //TODO:Test on Mac
}
<|endoftext|>