<commit_before>/**
 * Bindings to Kanso events
 */

var duality_events = require('duality/events'),
    dutils = require('duality/utils'),
    querystring = require('querystring'),
    templates = require('duality/templates'),
    session = require('session'),
    cookies = require('cookies'),
    users = require('users'),
    moment = require('moment'),
    _ = require('underscore'),
    shows = require('./shows'),
    data_records = require('./data_records'),
    //    objectpath = require('views/lib/objectpath'),
    utils = require('kujua-utils'),
    ksutils = require('./utils'),
    url = require('url'),
    settings = require('settings/root'),
    appinfo = require('./appinfo'),
    locale = require('locale'),
    ddoc = settings.name,
    app_settings = {};

/*var initDropdown = function() {
    if ($('.dropdown-toggle').dropdown) {
        $('.dropdown-toggle').dropdown();
    }
};*/

// wrap code spans with overflow auto. typically called after docsLoaded event
// is triggered.
var wrapCodeBlocks = function() {
    $('#docs-body code').each(function(idx, el) {
        var limit = 860,
            _el = $(this),
            width = _el.width();
        if (_el.hasClass('shorten')) {
            _el.wrap($('
').addClass('scroll-short'));
        } else if (width > limit) {
            _el.wrap($('
').addClass('scroll'));
        }
    });
};

exports.addHelpers = function() {
    // add helpers
    templates.addHelpers({
        translate: function(chunk, context, bodies, params) {
            var value = this.tap(params.value, chunk, context);

            return chunk.write($.kansotranslate(value));
        },
        formatDate: function(chunk, context, bodies, params) {
            var timestamp = Number(this.tap(params.timestamp, chunk, context)),
                format = this.tap(params.format, chunk, context);

            if (_.isNaN(timestamp)) {
                timestamp = this.tap(params.timestamp, chunk, context);
            }

            // todo use data_format setting if format is not passed in
            format = format || 'DD, MMM YYYY, HH:mm:ss ZZ';

            return chunk.write(moment(timestamp).format(format));
        },
        formName: function(chunk, context, bodies, params) {
            var form = this.tap(params.form, chunk, context);

            return chunk.write(ksutils.getFormTitle(form));
        },
        contact: function(chunk, context, bodies, params) {
            var entities = this.tapObject(params.entities, chunk, context),
                from = this.tap(params.from, chunk, context),
                to = this.tap(params.to, chunk, context),
                contact,
                clinic;

            if (entities) {

                contact = objectpath.get(
                    entities,
                    app_settings.contact_display_short
                );

                if (!contact) {
                    contact = entities.clinic && entities.clinic.name;
                }
            }

            if (!contact) {
                contact = from;
            }
            if (!contact) {
                contact = to;
            }
            if (!contact) {
                contact = '';
            }

            return chunk.write(contact);
        },
        tasksByState: function(chunk, context, bodies, params) {
            var array = this.tapArray(params.array, chunk, context),
                state = this.tap(params.state, chunk, context),
                matches;

            matches = _.filter(array, function(item) {
                return item.state === state;
            });

            return bodies.block(chunk, context.push(matches));
        },
        ifHasState: function(chunk, context, bodies, params) {
            var array = this.tapArray(params.array, chunk, context),
                state = this.tap(params.state, chunk, context),
                body = bodies.block,
                skip = bodies['else'],
                cond;

            cond = _.find(array, function(item) {
                return item && item.state === state;
            });

            if (cond) {
                return chunk.render(bodies.block, context);
            } else if (skip) {
                return chunk.render(bodies['else'], context);
            } else {
                return chunk;
            }
        },
        countByState: function(chunk, context, bodies, params) {
            var array1 = this.tapArray(params.array1, chunk, context),
                state = this.tap(params.state, chunk, context),
                matches,
                array = [];

            if (params.array2) {
                array1 = array1.concat(
                    this.tapArray(params.array2, chunk, context)
                );
            }

            matches = _.filter(array1, function(item) {
                return item && item.state === state;
            });

            return chunk.write(matches.length);
        },
        isAdmin: function(chunk, context, bodies, params) {
            var body = bodies.block,
                skip = bodies['else'];

            if (data_records.isAdmin) {
                return chunk.render(bodies.block, context);
            } else if (skip) {
                return chunk.render(skip, context);
            } else {
                return chunk;
            }
        },
        hasPermission: function(chunk, context, bodies, params) {
            var body = bodies.block,
                skip = bodies['else'],
                permission = this.tap(params.permission, chunk, context);

            if (utils.hasPerm(data_records.userCtx, permission)) {
                return chunk.render(bodies.block, context);
            } else if (skip) {
                return chunk.render(skip, context);
            } else {
                return chunk;
            }
        },
        idx: function(chunk, context, bodies) {
            if (bodies.block) {
                return bodies.block(chunk, context.push(context.stack.index));
            } else {
                return chunk;
            }
        },
        if : function(chunk, context, bodies, params) {
            var body = bodies.block,
                skip = bodies['else'];

            if (params && params.cond) {
                var cond = params.cond;

                cond = this.tap(cond, chunk, context);
                // eval expressions with given dust references
                if (eval(cond)) {
                    if (body) {
                        return chunk.render(bodies.block, context);
                    } else {
                        _console.log("Missing body block in the if helper!");
                        return chunk;
                    }
                }
                if (skip) {
                    return chunk.render(bodies['else'], context);
                }
            }
            // no condition
            else {
                _console.log("No condition given in the if helper!");
            }
            return chunk;
        }
    });

};

/**
 * The init method fires when the app is initially loaded from a page rendered
 * by CouchDB.  These should only be executed once when the app loads.
 */
duality_events.on('init', function() {

    try {
        app_settings = appinfo.getAppInfo.call(this);
    } catch (e) {
        shows.render500('Failed to retrieve settings.');
        console.error('Failed to retrieve settings.');
        throw e;
    }

    exports.addHelpers();

    // render top nav labels
    $('.navbar-header #emr_home').append('EMR - ' + $.kansotranslate('Home'));
    $('#topnav .nav .patients a').append(' ' + $.kansotranslate('Patients'));
    $('#topnav .nav .visits a').append(' ' + $.kansotranslate('Visits'));
    $('#topnav .nav .reports a').append(' ' + $.kansotranslate('Reports'));
    $('#topnav .nav .reports_calculated a').append(' ' + $.kansotranslate('Reports Calculated'));
    //    $('#topnav .nav .sms-forms-data a').append(' ' + $.kansotranslate('Export'));
    $('#topnav .nav .facilities a').append(' ' + $.kansotranslate('Facilities'));
    $('#topnav .nav .help a').append(' ' + $.kansotranslate('Help'));

    // Set version on all pages
    $('.version').text(settings.version);
    $('.clinic').text(settings.clinic);

    // Dynamic year for footer copyright
    $("#year").text(new Date().getFullYear());

    // add handler to docsPageLoader event for #supportedforms + p elements
    $(document).on('docsPageLoaded', wrapCodeBlocks);

    //$(document).on('click', '.spreadsheet-help .icon-question-sign', function(ev) {
    //    var el = $(ev.target);
    //    el.siblings('ul').toggle();
    //});

    // our version of bootstrap does not clear error on textareas
    $(document).on('focus', 'textarea', function(ev) {
        $(ev.target).closest('.control-group').removeClass('error');
    });

    $(document).on('click', '.controls .edit-mode .btn', data_records.handleUpdateDropdown);
    $(document).on('click', '.add-message button, .add-message a', data_records.handleSendMessage);

});

/**
 * The sessionChange event fires when the app is first loaded and the user's
 * session information becomes available. It is also fired whenever a change
 * to the user's session is detected, for example after logging in or out.
 */

// stores a reference to the modal dialog
var m;

session.on('change', function(userCtx, req) {

    var users = require('users')

    try {
        app_settings = appinfo.getAppInfo.call(this);
    } catch (e) {
        shows.render500('Failed to retrieve settings.');
        console.error('Failed to retrieve settings.');
        throw e;
    }
    exports.addHelpers();

    var isAdmin = utils.isUserAdmin(userCtx);

    _.extend(data_records, {
        isAdmin: isAdmin,
        userCtx: userCtx
    });

    if (!$('#session_menu').length) {
        $('#topnav .pull-right').append(
            '

'
        );
    }
    var el;

    if (userCtx.name) {
        el = $(
            '
' +
            '' +
            ' ' + userCtx.name + ' ' +
            '' +
            '' +
            '
' +
            '
Logout
' +
            '
' +
            '
'
        );
        console.log(userCtx)
        //$('.dropdown-toggle', el).click(data_records.handleUpdateDropdown);
        $('.logout', el).click(function(ev) {
            ev.preventDefault();
            session.logout(function(err, resp) {
                location.href = dutils.getBaseURL();
            });
            return false;
        });
    } else {
        el = $(
            '
' +
            'Login' +
            '
'
        );

        if (m) {
            // clear previous modal dialog
            m.modal('hide');
            m.data('modal', null);
            m.remove();
        }
        m = $(templates.render("login_modal.html", {
            userCtx: userCtx
        }, {}));

        var submitHandler = function(ev) {
            ev.preventDefault();

            var username = $('#id_username', m).val();
            var password = $('#id_password', m).val();

            $('.alert', m).remove();
            $('.help-inline', m).remove();
            $('.control-group', m).removeClass('error');
            $('.controls', m).show(); // sometimes these get hidden

            var username_cg = $('#id_username').parents('.control-group');
            var password_cg = $('#id_password').parents('.control-group');
            var errors = false;

            if (!username) {
                username_cg.addClass('error');
                $('#id_username').attr("placeholder", "Username Required");
                $('#id_username').parent().addClass("has-error");
                errors = true;
            }
            if (!password) {
                password_cg.addClass('error');
                $('#id_password').attr("placeholder", "Password Required");
                $('#id_password').parent().addClass("has-error");
                errors = true;
            }
            if (errors) {
                return false;
            }

            session.login(username, password, function(err, usrCtx) {
                if (err) {
                    var msg = err.toString();
                    $('form', m).after(
                        '
' + msg + '
'
                    );
                } else {
                    m.modal('hide');
                    users.get(username, function (err, doc) {
//                        if (typeof cookies.readBrowserCookie("userLang") != 'undefined') {
                            cookies.setBrowserCookie(req, {name: "userLang", value: doc.language})
 //                       }
                    })

                    location.href = dutils.getBaseURL();
                }
            });
            return false;
        };

        $('form', m).submit(submitHandler);

        // fake form submit event
        $('input', m).keyup(function(ev) {
            if (ev.keyCode === 13) {
                return submitHandler.apply(this, arguments);
            }
        });

        $('.btn-primary', m).click(submitHandler);
        $('.btn-close', m).click(function() {
            m.modal('hide');
        });
        $('.btn-cancel', m).click(function() {
            m.modal('hide');
        });

        $('.login', el).click(function(ev) {
            ev.preventDefault();
            m.modal('show');
            return false;
        });

        m.on('shown.bs.modal', function() {
            $('#id_username').focus();
        })
    }

    for (lang in app_settings.locales) {
        $('.dropdown-menu', el).append(
            '
' + app_settings.locales[lang] + '
'
        );
        $('.dropdown-menu .lang', el).click(function(ev) {
            ev.preventDefault();
            console.log(ev.target.id)
            cookies.setBrowserCookie(req, {name: "userLang", value: ev.target.id})
            location.href = dutils.getBaseURL();
            return false;
        });
    }

    $('#session_menu').replaceWith(el);

    if (utils.isDbAdmin(userCtx)) {
        $('.dropdown-menu', el).append(
            '
Manage Users
'
        );
    }
    $('#session_menu').replaceWith(el);

    // hide the nav items from non-admin users
    if (_.difference(['district_admin', 'national_admin', '_admin'], userCtx.roles).length === 3) {
        $('.navbar .nav li').hide();
        $('.navbar .nav .docs').show();
    } else {
        $('.navbar .nav li').show();
    }
    $('#topnav .navbar-right').append(el);

});

/**
 * The updateFailure event fires when an update function returns a document as
 * the first part of an array, but the client-side request to update the
 * document fails.
 */

duality_events.on('updateFailure', function(err, info, req, res, doc) {
    alert(err.message || err.toString());
});
<commit_msg>Making login screen and other aspects of the interface translatable<commit_after>/**
 * Bindings to Kanso events
 */

var duality_events = require('duality/events'),
    dutils = require('duality/utils'),
    querystring = require('querystring'),
    templates = require('duality/templates'),
    session = require('session'),
    cookies = require('cookies'),
    users = require('users'),
    moment = require('moment'),
    _ = require('underscore'),
    shows = require('./shows'),
    data_records = require('./data_records'),
    //    objectpath = require('views/lib/objectpath'),
    utils = require('kujua-utils'),
    ksutils = require('./utils'),
    url = require('url'),
    settings = require('settings/root'),
    appinfo = require('./appinfo'),
    locale = require('locale'),
    ddoc = settings.name,
    app_settings = {};

/*var initDropdown = function() {
    if ($('.dropdown-toggle').dropdown) {
        $('.dropdown-toggle').dropdown();
    }
};*/

// wrap code spans with overflow auto. typically called after docsLoaded event
// is triggered.
var wrapCodeBlocks = function() {
    $('#docs-body code').each(function(idx, el) {
        var limit = 860,
            _el = $(this),
            width = _el.width();
        if (_el.hasClass('shorten')) {
            _el.wrap($('
').addClass('scroll-short'));
        } else if (width > limit) {
            _el.wrap($('
').addClass('scroll'));
        }
    });
};

exports.addHelpers = function() {
    // add helpers
    templates.addHelpers({
        translate: function(chunk, context, bodies, params) {
            var value = this.tap(params.value, chunk, context);

            return chunk.write($.kansotranslate(value));
        },
        formatDate: function(chunk, context, bodies, params) {
            var timestamp = Number(this.tap(params.timestamp, chunk, context)),
                format = this.tap(params.format, chunk, context);

            if (_.isNaN(timestamp)) {
                timestamp = this.tap(params.timestamp, chunk, context);
            }

            // todo use data_format setting if format is not passed in
            format = format || 'DD, MMM YYYY, HH:mm:ss ZZ';

            return chunk.write(moment(timestamp).format(format));
        },
        formName: function(chunk, context, bodies, params) {
            var form = this.tap(params.form, chunk, context);

            return chunk.write(ksutils.getFormTitle(form));
        },
        contact: function(chunk, context, bodies, params) {
            var entities = this.tapObject(params.entities, chunk, context),
                from = this.tap(params.from, chunk, context),
                to = this.tap(params.to, chunk, context),
                contact,
                clinic;

            if (entities) {

                contact = objectpath.get(
                    entities,
                    app_settings.contact_display_short
                );

                if (!contact) {
                    contact = entities.clinic && entities.clinic.name;
                }
            }

            if (!contact) {
                contact = from;
            }
            if (!contact) {
                contact = to;
            }
            if (!contact) {
                contact = '';
            }

            return chunk.write(contact);
        },
        tasksByState: function(chunk, context, bodies, params) {
            var array = this.tapArray(params.array, chunk, context),
                state = this.tap(params.state, chunk, context),
                matches;

            matches = _.filter(array, function(item) {
                return item.state === state;
            });

            return bodies.block(chunk, context.push(matches));
        },
        ifHasState: function(chunk, context, bodies, params) {
            var array = this.tapArray(params.array, chunk, context),
                state = this.tap(params.state, chunk, context),
                body = bodies.block,
                skip = bodies['else'],
                cond;

            cond = _.find(array, function(item) {
                return item && item.state === state;
            });

            if (cond) {
                return chunk.render(bodies.block, context);
            } else if (skip) {
                return chunk.render(bodies['else'], context);
            } else {
                return chunk;
            }
        },
        countByState: function(chunk, context, bodies, params) {
            var array1 = this.tapArray(params.array1, chunk, context),
                state = this.tap(params.state, chunk, context),
                matches,
                array = [];

            if (params.array2) {
                array1 = array1.concat(
                    this.tapArray(params.array2, chunk, context)
                );
            }

            matches = _.filter(array1, function(item) {
                return item && item.state === state;
            });

            return chunk.write(matches.length);
        },
        isAdmin: function(chunk, context, bodies, params) {
            var body = bodies.block,
                skip = bodies['else'];

            if (data_records.isAdmin) {
                return chunk.render(bodies.block, context);
            } else if (skip) {
                return chunk.render(skip, context);
            } else {
                return chunk;
            }
        },
        hasPermission: function(chunk, context, bodies, params) {
            var body = bodies.block,
                skip = bodies['else'],
                permission = this.tap(params.permission, chunk, context);

            if (utils.hasPerm(data_records.userCtx, permission)) {
                return chunk.render(bodies.block, context);
            } else if (skip) {
                return chunk.render(skip, context);
            } else {
                return chunk;
            }
        },
        idx: function(chunk, context, bodies) {
            if (bodies.block) {
                return bodies.block(chunk, context.push(context.stack.index));
            } else {
                return chunk;
            }
        },
        if : function(chunk, context, bodies, params) {
            var body = bodies.block,
                skip = bodies['else'];

            if (params && params.cond) {
                var cond = params.cond;

                cond = this.tap(cond, chunk, context);
                // eval expressions with given dust references
                if (eval(cond)) {
                    if (body) {
                        return chunk.render(bodies.block, context);
                    } else {
                        _console.log("Missing body block in the if helper!");
                        return chunk;
                    }
                }
                if (skip) {
                    return chunk.render(bodies['else'], context);
                }
            }
            // no condition
            else {
                _console.log("No condition given in the if helper!");
            }
            return chunk;
        }
    });

};

/**
 * The init method fires when the app is initially loaded from a page rendered
 * by CouchDB.  These should only be executed once when the app loads.
 */
duality_events.on('init', function() {

    try {
        app_settings = appinfo.getAppInfo.call(this);
    } catch (e) {
        shows.render500('Failed to retrieve settings.');
        console.error('Failed to retrieve settings.');
        throw e;
    }

    exports.addHelpers();

    // render top nav labels
    $('.navbar-header #emr_home').append('EMR - ' + $.kansotranslate('Home'));
    $('#topnav .nav .patients a').append(' ' + $.kansotranslate('Patients'));
    $('#topnav .nav .visits a').append(' ' + $.kansotranslate('Visits'));
    $('#topnav .nav .reports a').append(' ' + $.kansotranslate('Reports'));
    $('#topnav .nav .reports_calculated a').append(' ' + $.kansotranslate('Reports Calculated'));
    //    $('#topnav .nav .sms-forms-data a').append(' ' + $.kansotranslate('Export'));
    $('#topnav .nav .facilities a').append(' ' + $.kansotranslate('Facilities'));
    $('#topnav .nav .help a').append(' ' + $.kansotranslate('Help'));

    // Set version on all pages
    $('.version').text(settings.version);
    $('.clinic').text(settings.clinic);

    // Dynamic year for footer copyright
    $("#year").text(new Date().getFullYear());

    // add handler to docsPageLoader event for #supportedforms + p elements
    $(document).on('docsPageLoaded', wrapCodeBlocks);

    //$(document).on('click', '.spreadsheet-help .icon-question-sign', function(ev) {
    //    var el = $(ev.target);
    //    el.siblings('ul').toggle();
    //});

    // our version of bootstrap does not clear error on textareas
    $(document).on('focus', 'textarea', function(ev) {
        $(ev.target).closest('.control-group').removeClass('error');
    });

    $(document).on('click', '.controls .edit-mode .btn', data_records.handleUpdateDropdown);
    $(document).on('click', '.add-message button, .add-message a', data_records.handleSendMessage);

});

/**
 * The sessionChange event fires when the app is first loaded and the user's
 * session information becomes available. It is also fired whenever a change
 * to the user's session is detected, for example after logging in or out.
 */

// stores a reference to the modal dialog
var m;

session.on('change', function(userCtx, req) {

    var users = require('users')

    try {
        app_settings = appinfo.getAppInfo.call(this);
    } catch (e) {
        shows.render500('Failed to retrieve settings.');
        console.error('Failed to retrieve settings.');
        throw e;
    }
    exports.addHelpers();

    var isAdmin = utils.isUserAdmin(userCtx);

    _.extend(data_records, {
        isAdmin: isAdmin,
        userCtx: userCtx
    });

    if (!$('#session_menu').length) {
        $('#topnav .pull-right').append(
            '

'
        );
    }
    var el;

    if (userCtx.name) {
        log("Logged in.")
        el = $(
            '
' +
            '' +
            ' ' + userCtx.name + ' ' +
            '' +
            '' +
            '
' +
            '
Logout
' +
            '
' +
            '
'
        );
        console.log(userCtx)
        //$('.dropdown-toggle', el).click(data_records.handleUpdateDropdown);
        $('.logout', el).click(function(ev) {
            ev.preventDefault();
            session.logout(function(err, resp) {
                location.href = dutils.getBaseURL();
            });
            return false;
        });
    } else {
        log("Not logged in.")
        el = $(
            '
' +
            '' + $.kansotranslate('Login') + '' +
            '
'
        );

        if (m) {
            // clear previous modal dialog
            m.modal('hide');
            m.data('modal', null);
            m.remove();
        }
        m = $(templates.render("login_modal.html", {
            userCtx: userCtx
        }, {}));

        var submitHandler = function(ev) {
            ev.preventDefault();

            var username = $('#id_username', m).val();
            var password = $('#id_password', m).val();

            $('.alert', m).remove();
            $('.help-inline', m).remove();
            $('.control-group', m).removeClass('error');
            $('.controls', m).show(); // sometimes these get hidden

            var username_cg = $('#id_username').parents('.control-group');
            var password_cg = $('#id_password').parents('.control-group');
            var errors = false;

            if (!username) {
                username_cg.addClass('error');
                $('#id_username').attr("placeholder", $.kansotranslate('Username Required'));
                $('#id_username').parent().addClass("has-error");
                errors = true;
            }
            if (!password) {
                password_cg.addClass('error');
                $('#id_password').attr("placeholder", $.kansotranslate('Password Required'));
                $('#id_password').parent().addClass("has-error");
                errors = true;
            }
            if (errors) {
                return false;
            }

            session.login(username, password, function(err, usrCtx) {
                if (err) {
                    var msg = err.toString();
                    $('form', m).after(
                        '
' + msg + '
'
                    );
                } else {
                    m.modal('hide');
                    users.get(username, function (err, doc) {
//                        if (typeof cookies.readBrowserCookie("userLang") != 'undefined') {
                            cookies.setBrowserCookie(req, {name: "userLang", value: doc.language})
 //                       }
                    })

                    location.href = dutils.getBaseURL();
                }
            });
            return false;
        };

        $('form', m).submit(submitHandler);

        // fake form submit event
        $('input', m).keyup(function(ev) {
            if (ev.keyCode === 13) {
                return submitHandler.apply(this, arguments);
            }
        });

        $('.btn-primary', m).click(submitHandler);
        $('.btn-close', m).click(function() {
            m.modal('hide');
        });
        $('.btn-cancel', m).click(function() {
            m.modal('hide');
        });

        $('.login', el).click(function(ev) {
            ev.preventDefault();
            m.modal('show');
            return false;
        });

        m.on('shown.bs.modal', function() {
            $('#id_username').focus();
        })
    }

    for (lang in app_settings.locales) {
        $('.dropdown-menu', el).append(
            '
' + app_settings.locales[lang] + '
'
        );
        $('.dropdown-menu .lang', el).click(function(ev) {
            ev.preventDefault();
            console.log(ev.target.id)
            cookies.setBrowserCookie(req, {name: "userLang", value: ev.target.id})
            location.href = dutils.getBaseURL();
            return false;
        });
    }

    $('#session_menu').replaceWith(el);

    if (utils.isDbAdmin(userCtx)) {
        $('.dropdown-menu', el).append(
            '
Administration
'
        );
    }
    $('#session_menu').replaceWith(el);

    // hide the nav items from non-admin users
    if (_.difference(['district_admin', 'national_admin', '_admin'], userCtx.roles).length === 3) {
        $('.navbar .nav li').hide();
        $('.navbar .nav .docs').show();
    } else {
        $('.navbar .nav li').show();
    }
    $('#topnav .navbar-right').append(el);

});

/**
 * The updateFailure event fires when an update function returns a document as
 * the first part of an array, but the client-side request to update the
 * document fails.
 */

duality_events.on('updateFailure', function(err, info, req, res, doc) {
    alert(err.message || err.toString());
});
<|endoftext|>


<commit_before>module.exports = function(mongoose) {
	'use strict';

	function sanitize(str) {
		// santizes regex escapes
		return str.replace(/\W\s/ig, '\\$&');
	}

	mongoose.Query.prototype.filter = function (options) {
		if (!options || !options.filters) {
			return this;
		}

		var
			mandatory = options.filters.mandatory || {},
			optional = options.filters.optional || {},
			self = this;

		var applyWhere = function (spec, buildRegex) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					var val = buildRegex(spec[key]);

					self.where(key, val);
				}
			}
		};

		var applyWhereGreaterThan = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).gt(spec[key]);
				}
			}
		};

		var applyWhereGreaterThanEqual = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).gte(spec[key]);
				}
			}
		};

		var applyWhereLesserThan = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).lt(spec[key]);
				}
			}
		};

		var applyWhereLesserThanEqual = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).lte(spec[key]);
				}
			}
		};

		var applyOptionals = function(optional) {
			var items = [];

			var populate = function (key, value, buildRegex) {
				var
					items = [],
					item = {};

				if (value instanceof Array && value.length) {
					value.forEach(function (val) {
						item = {};
						item[key] = buildRegex(val);
						items.push(item);
					});

					return items;
				} else {
					item[key] = buildRegex(value);

					return item;
				}
			};

			var parse = function(spec, buildRegex) {
				var
					parsedItems = null,
					result = null;

				if (!spec) {
					return null;
				}

				for (var key in spec) {
					if (spec.hasOwnProperty(key)) {
						result = populate(key, spec[key], buildRegex);

						if (result instanceof Array && result.length) {
							parsedItems = result;
						} else {
							if (!parsedItems) {
								parsedItems = [];
							}

							parsedItems.push(result);
						}
					}
				}
				return parsedItems;
			};

			items = parse(optional.contains, regexContains);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}

			items = parse(optional.endsWith, regexEndsWith);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}

			items = parse(optional.startsWith, regexStartsWith);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}

			items = parse(optional.exact, regexExact);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}
		};

		var regexContains = function (val) {
			if (typeof val === 'string') {
				return new RegExp(sanitize(val), 'i');
			}

			return val;
		};

		/**
		 * Assumes field type is a string
		 **/
		var regexEndsWith = function (val) {
			return new RegExp(sanitize(val) + '$', 'i');
		};

		var regexExact = function (val) {
			if (isNaN(val) && typeof val === 'string') {
				switch(val.toLowerCase()) {
					case 'false' :
						return false;
					case 'true' :
						return true;
					default :
						return new RegExp('^' + sanitize(val) + '$', 'i');
				}
			}

			return val;
		};

		/**
		 * Assumes field type is a string
		 **/
		var regexStartsWith = function (val) {
			return new RegExp('^' + sanitize(val), 'i');
		};

		// MANDATORY
		applyWhere(mandatory.contains, regexContains);
		applyWhere(mandatory.endsWith, regexEndsWith);
		applyWhere(mandatory.startsWith, regexStartsWith);
		applyWhere(mandatory.exact, regexExact);

		applyWhereGreaterThan(mandatory.greaterThan || mandatory.gt || {});
		applyWhereGreaterThanEqual(mandatory.greaterThanEqual || mandatory.gte || {});
		applyWhereLesserThan(mandatory.lessThan || mandatory.lt || {});
		applyWhereLesserThanEqual(mandatory.lessThanEqual || mandatory.lte || {});

		// OPTIONAL
		applyOptionals(optional);

		return self;
	};
};
<commit_msg>correcting an issue in the sanitation where word boundaries ignored the opening paranthesis<commit_after>module.exports = function(mongoose) {
	'use strict';

	function sanitize(str) {
		// santizes regex escapes
		return str.replace(/[\W\s]/ig, '\\$&');
	}

	mongoose.Query.prototype.filter = function (options) {
		if (!options || !options.filters) {
			return this;
		}

		var
			mandatory = options.filters.mandatory || {},
			optional = options.filters.optional || {},
			self = this;

		var applyWhere = function (spec, buildRegex) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					var val = buildRegex(spec[key]);

					self.where(key, val);
				}
			}
		};

		var applyWhereGreaterThan = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).gt(spec[key]);
				}
			}
		};

		var applyWhereGreaterThanEqual = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).gte(spec[key]);
				}
			}
		};

		var applyWhereLesserThan = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).lt(spec[key]);
				}
			}
		};

		var applyWhereLesserThanEqual = function (spec) {
			for (var key in spec) {
				if (spec.hasOwnProperty(key)) {
					self.where(key).lte(spec[key]);
				}
			}
		};

		var applyOptionals = function(optional) {
			var items = [];

			var populate = function (key, value, buildRegex) {
				var
					items = [],
					item = {};

				if (value instanceof Array && value.length) {
					value.forEach(function (val) {
						item = {};
						item[key] = buildRegex(val);
						items.push(item);
					});

					return items;
				} else {
					item[key] = buildRegex(value);

					return item;
				}
			};

			var parse = function(spec, buildRegex) {
				var
					parsedItems = null,
					result = null;

				if (!spec) {
					return null;
				}

				for (var key in spec) {
					if (spec.hasOwnProperty(key)) {
						result = populate(key, spec[key], buildRegex);

						if (result instanceof Array && result.length) {
							parsedItems = result;
						} else {
							if (!parsedItems) {
								parsedItems = [];
							}

							parsedItems.push(result);
						}
					}
				}
				return parsedItems;
			};

			items = parse(optional.contains, regexContains);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}

			items = parse(optional.endsWith, regexEndsWith);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}

			items = parse(optional.startsWith, regexStartsWith);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}

			items = parse(optional.exact, regexExact);
			if (items && items instanceof Array && items.length) {
				self.or(items);
			}
		};

		var regexContains = function (val) {
			if (typeof val === 'string') {
				return new RegExp(sanitize(val), 'i');
			}

			return val;
		};

		/**
		 * Assumes field type is a string
		 **/
		var regexEndsWith = function (val) {
			return new RegExp(sanitize(val) + '$', 'i');
		};

		var regexExact = function (val) {
			if (isNaN(val) && typeof val === 'string') {
				switch(val.toLowerCase()) {
					case 'false' :
						return false;
					case 'true' :
						return true;
					default :
						return new RegExp('^' + sanitize(val) + '$', 'i');
				}
			}

			return val;
		};

		/**
		 * Assumes field type is a string
		 **/
		var regexStartsWith = function (val) {
			return new RegExp('^' + sanitize(val), 'i');
		};

		// MANDATORY
		applyWhere(mandatory.contains, regexContains);
		applyWhere(mandatory.endsWith, regexEndsWith);
		applyWhere(mandatory.startsWith, regexStartsWith);
		applyWhere(mandatory.exact, regexExact);

		applyWhereGreaterThan(mandatory.greaterThan || mandatory.gt || {});
		applyWhereGreaterThanEqual(mandatory.greaterThanEqual || mandatory.gte || {});
		applyWhereLesserThan(mandatory.lessThan || mandatory.lt || {});
		applyWhereLesserThanEqual(mandatory.lessThanEqual || mandatory.lte || {});

		// OPTIONAL
		applyOptionals(optional);

		return self;
	};
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var path = require('path'),
    fs = require('fs'),
    sys = require('util'),
    chalk = require('chalk'),
    mkdirp = require('mkdirp'),
    rtlcss = require('../lib/rtlcss'),
    configLoader = require('../lib/config-loader')
;

var input, output, directory,
    config, silent, currentErrorcode,
    arg, args = process.argv.slice(2),
    shouldBreak = false
;

process.on('exit', function() { process.reallyExit(currentErrorcode) });

function printWarning (){
  console.log(chalk.yellow.apply(this,printWarning.arguments));
}

function printInfo (){
  console.log(chalk.green.apply(this,printInfo.arguments));
}

function printError (){
  console.log(chalk.red.apply(this,printError.arguments));
}

function printHelp(){
  console.log('Usage: rtlcss [option option=parameter ...] [source] [destination]');
  console.log('');
  var options =
  [
      'Option '         , 'Description ',
      '--------------'  , '----------------------------------------------',
      '-h,--help'       , 'Print help (this message) and exit.',
      '-v,--version'    , 'Print version number and exit.',
      '-c,--config'     , 'Path to configuration settings file.',
      '- ,--stdin'      , 'Read from stdin stream.',
      '-d,--dirctory'   , 'Process all *.css files from input directory (recursive).',
      '-s,--silent'     , 'Silent mode, no warnings or errors are printed.'
  ];

  for(var x=0;x<options.length;x++){
    console.log(options[x++],'\t',options[x]);
  }
  console.log('');
  console.log('*If no destination is specified, output will be written to the same input folder as {source}.rtl.{ext}');
  console.log('');
  printInfo('RTLCSS version: ' + require('../package.json').version);
  printInfo('Report issues to: https://github.com/MohammadYounes/rtlcss/issues');
}

while(arg = args.shift()){
  switch(arg){
    case '-h':
    case '--help':
      printHelp();
      shouldBreak = true;
      break;
    case '-v':
    case '--version':
      printInfo('rtlcss version: ' + require('../package.json').version);
      shouldBreak = true;
      break;
    case '-c':
    case '--config':
      arg = args.shift();
      try
      {
        config = configLoader.load(path.resolve(arg));
      }
      catch(e)
      {
        printError('rtlcss: invalid config file. ', e);
        shouldBreak = true;
        currentErrorcode = 1;
      }
      break;
    case '-d':
    case '--directory':
      directory = true;
      break;
    case '-s':
    case '--silent':
      console.log = function(){};
      break;
    case '-':
    case '--stdin':
      input = '-';
      break;
    default:
      if(arg[0] == '-'){
        printError('rtlcss: unknown option. ' + arg);
        shouldBreak = true;
      }else{
        if(!input)
          input  = path.resolve(arg);
        else if(!output)
          output = path.resolve(arg);
      }
      break;
  }
}

if(shouldBreak){
  return;
}

if (!directory && !input) {
  printError('rtlcss: no input file');
  console.log('');
  printHelp();
  return;
}
if(!config && input !== '-'){
  try
  {
    var cwd = input;
    if(directory !== true){
      cwd = path.dirname(input);
    }
    config = configLoader.load(null, cwd);
  }catch(e){
    printError('rtlcss: invalid config file. ', e);
    currentErrorcode = 1;
    return;
  }
}

if(!output && input !== '-'){
  if(directory !== true){
    output = path.extname(input) ? input.replace(/\.[^.]*$/, function(ext){ return '.rtl' + ext;}) : input + '.rtl';
  }
  else{
    output = input;
  }
}

var processCSSFile = function (e, data, outputName) {
  if (e) {
    printError('rtlcss: ' + e.message);
    return;
  }
  var result, opt = { map: undefined, from:undefined, to:undefined};
  if(!config){
    printWarning('rtlcss: Warning! No config present, using defaults.');
    result = rtlcss().process(data, opt);
  }else{
    if(config.map === true && input !== '-'){
      opt.map = config.map;
      opt.from = input;
      opt.to = output;
    }
    result = rtlcss(config.options,
                    config.rules,
                    config.declarations,
                    config.properties).process(data, opt);
  }

  if (output) {
    var savePath = outputName;
    if(directory !== true){
      savePath = output;
    }
    printInfo('Saving:', savePath);
    fs.writeFile(savePath, result.css, 'utf8', function(err){ err && printError(err); });
    if(opt.map == true){
      fs.writeFile(savePath + '.map', result.map, 'utf8', function(err){  err && printError(err); } );
    }
  } else {
    sys.print(result.css);
  }
};

var walk = function(dir, done) {
  fs.readdir(dir, function (error, list) {
    if (error) {
      return done(error);
    }
    var i = 0;
    (function next() {
      var file = list[i++];
      if (!file) {
        return done(null);
      }
      file = dir + path.sep  + file;
      fs.stat(file, function (error, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function (error) {
            next();
          });
        } else {
          //process only *.css
          if (/\.(css)$/.test(file)) {
            //compute output directory
            var relativePath = path.relative(input,file).split(path.sep);
            relativePath.pop();
            relativePath.push(path.basename(file).replace(".css", ".rtl.css"));

            //set rtl file name
            var rtlFile = path.join(output,relativePath.join(path.sep));

            //create output directory if it does not exist
            var dirName = path.dirname(rtlFile);
            if(!fs.existsSync(dirName))
              mkdirp.sync(dirName);

            //read and process the file.
            fs.readFile(file, 'utf8',function(e,data){
                try{
                  processCSSFile(e,data,rtlFile);
                }catch(e){
                  printError('rtlcss: error processing file',file);
                  printError(e);
                }
              });
          }
          next();
        }
      });
    })();
  });
};

if (input != '-') {
  if(directory !== true){
    fs.stat(input, function (error, stat) {
      if (stat && stat.isDirectory()){
        printError('rtlcss: Input expected to be a file, use -d option to process a directory.');
      }else{
        fs.readFile(input, 'utf8', function(e,data){
          try{
            processCSSFile(e,data);
          }catch(e){
            printError('rtlcss: error processing file',input);
            printError(e);
          }
        });
      }
    });
  }else{
    walk(input, function(error){
      if(error)
        printError('rtlcss: '+ error);
    });
  }
} else {
  process.stdin.resume();
  process.stdin.setEncoding('utf8');

  var buffer = '';
  process.stdin.on('data', function(data) {
    buffer += data;
  });
  process.on('SIGINT', function(){
    processCSSFile(false, buffer);
    process.exit();
  });
  process.stdin.on('end', function() {
    processCSSFile(false, buffer);
  });
}
<commit_msg>CLI: Switch to UNIX line endings<commit_after>#!/usr/bin/env node

var path = require('path'),
    fs = require('fs'),
    sys = require('util'),
    chalk = require('chalk'),
    mkdirp = require('mkdirp'),
    rtlcss = require('../lib/rtlcss'),
    configLoader = require('../lib/config-loader')
;

var input, output, directory,
    config, silent, currentErrorcode,
    arg, args = process.argv.slice(2),
    shouldBreak = false
;

process.on('exit', function() { process.reallyExit(currentErrorcode) });

function printWarning (){
  console.log(chalk.yellow.apply(this,printWarning.arguments));
}

function printInfo (){
  console.log(chalk.green.apply(this,printInfo.arguments));
}

function printError (){
  console.log(chalk.red.apply(this,printError.arguments));
}

function printHelp(){
  console.log('Usage: rtlcss [option option=parameter ...] [source] [destination]');
  console.log('');
  var options =
  [
      'Option '         , 'Description ',
      '--------------'  , '----------------------------------------------',
      '-h,--help'       , 'Print help (this message) and exit.',
      '-v,--version'    , 'Print version number and exit.',
      '-c,--config'     , 'Path to configuration settings file.',
      '- ,--stdin'      , 'Read from stdin stream.',
      '-d,--dirctory'   , 'Process all *.css files from input directory (recursive).',
      '-s,--silent'     , 'Silent mode, no warnings or errors are printed.'
  ];

  for(var x=0;x<options.length;x++){
    console.log(options[x++],'\t',options[x]);
  }
  console.log('');
  console.log('*If no destination is specified, output will be written to the same input folder as {source}.rtl.{ext}');
  console.log('');
  printInfo('RTLCSS version: ' + require('../package.json').version);
  printInfo('Report issues to: https://github.com/MohammadYounes/rtlcss/issues');
}

while(arg = args.shift()){
  switch(arg){
    case '-h':
    case '--help':
      printHelp();
      shouldBreak = true;
      break;
    case '-v':
    case '--version':
      printInfo('rtlcss version: ' + require('../package.json').version);
      shouldBreak = true;
      break;
    case '-c':
    case '--config':
      arg = args.shift();
      try
      {
        config = configLoader.load(path.resolve(arg));
      }
      catch(e)
      {
        printError('rtlcss: invalid config file. ', e);
        shouldBreak = true;
        currentErrorcode = 1;
      }
      break;
    case '-d':
    case '--directory':
      directory = true;
      break;
    case '-s':
    case '--silent':
      console.log = function(){};
      break;
    case '-':
    case '--stdin':
      input = '-';
      break;
    default:
      if(arg[0] == '-'){
        printError('rtlcss: unknown option. ' + arg);
        shouldBreak = true;
      }else{
        if(!input)
          input  = path.resolve(arg);
        else if(!output)
          output = path.resolve(arg);
      }
      break;
  }
}

if(shouldBreak){
  return;
}

if (!directory && !input) {
  printError('rtlcss: no input file');
  console.log('');
  printHelp();
  return;
}
if(!config && input !== '-'){
  try
  {
    var cwd = input;
    if(directory !== true){
      cwd = path.dirname(input);
    }
    config = configLoader.load(null, cwd);
  }catch(e){
    printError('rtlcss: invalid config file. ', e);
    currentErrorcode = 1;
    return;
  }
}

if(!output && input !== '-'){
  if(directory !== true){
    output = path.extname(input) ? input.replace(/\.[^.]*$/, function(ext){ return '.rtl' + ext;}) : input + '.rtl';
  }
  else{
    output = input;
  }
}

var processCSSFile = function (e, data, outputName) {
  if (e) {
    printError('rtlcss: ' + e.message);
    return;
  }
  var result, opt = { map: undefined, from:undefined, to:undefined};
  if(!config){
    printWarning('rtlcss: Warning! No config present, using defaults.');
    result = rtlcss().process(data, opt);
  }else{
    if(config.map === true && input !== '-'){
      opt.map = config.map;
      opt.from = input;
      opt.to = output;
    }
    result = rtlcss(config.options,
                    config.rules,
                    config.declarations,
                    config.properties).process(data, opt);
  }

  if (output) {
    var savePath = outputName;
    if(directory !== true){
      savePath = output;
    }
    printInfo('Saving:', savePath);
    fs.writeFile(savePath, result.css, 'utf8', function(err){ err && printError(err); });
    if(opt.map == true){
      fs.writeFile(savePath + '.map', result.map, 'utf8', function(err){  err && printError(err); } );
    }
  } else {
    sys.print(result.css);
  }
};

var walk = function(dir, done) {
  fs.readdir(dir, function (error, list) {
    if (error) {
      return done(error);
    }
    var i = 0;
    (function next() {
      var file = list[i++];
      if (!file) {
        return done(null);
      }
      file = dir + path.sep  + file;
      fs.stat(file, function (error, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function (error) {
            next();
          });
        } else {
          //process only *.css
          if (/\.(css)$/.test(file)) {
            //compute output directory
            var relativePath = path.relative(input,file).split(path.sep);
            relativePath.pop();
            relativePath.push(path.basename(file).replace(".css", ".rtl.css"));

            //set rtl file name
            var rtlFile = path.join(output,relativePath.join(path.sep));

            //create output directory if it does not exist
            var dirName = path.dirname(rtlFile);
            if(!fs.existsSync(dirName))
              mkdirp.sync(dirName);

            //read and process the file.
            fs.readFile(file, 'utf8',function(e,data){
                try{
                  processCSSFile(e,data,rtlFile);
                }catch(e){
                  printError('rtlcss: error processing file',file);
                  printError(e);
                }
              });
          }
          next();
        }
      });
    })();
  });
};

if (input != '-') {
  if(directory !== true){
    fs.stat(input, function (error, stat) {
      if (stat && stat.isDirectory()){
        printError('rtlcss: Input expected to be a file, use -d option to process a directory.');
      }else{
        fs.readFile(input, 'utf8', function(e,data){
          try{
            processCSSFile(e,data);
          }catch(e){
            printError('rtlcss: error processing file',input);
            printError(e);
          }
        });
      }
    });
  }else{
    walk(input, function(error){
      if(error)
        printError('rtlcss: '+ error);
    });
  }
} else {
  process.stdin.resume();
  process.stdin.setEncoding('utf8');

  var buffer = '';
  process.stdin.on('data', function(data) {
    buffer += data;
  });
  process.on('SIGINT', function(){
    processCSSFile(false, buffer);
    process.exit();
  });
  process.stdin.on('end', function() {
    processCSSFile(false, buffer);
  });
}<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Command line client for seguir - used to setup a server.
 */
var inquirer = require('inquirer');
var program = require('commander');
var _ = require('lodash');
var path = require('path');

program
  .version('0.0.1')
  .option('-s, --setup [file]', 'Use setup file')
  .option('-c, --config [file]', 'Use config file')
  .option('-d, --database [database]', 'Use database type cassandra|postgres')
  .parse(process.argv);

var database = program.database || 'cassandra';
var defaultConfig = '../server/config/' + database;
var configFn;

if (program.config) {
  var configFile = path.resolve('.', program.config);
  try {
    configFn = require(configFile);
  } catch(ex) {
    console.log('Cant open config: ' + ex.message);
    process.exit(1);
  }
} else {
  var originalConfig = require(defaultConfig);
  configFn = function (next) {
    next(null, originalConfig);
  };
}

function error (err) {
  console.log('Error: ' + err.message);
  process.exit(1);
}

// Async load config
configFn(function (err, config) {

  if (err) return error(err);

  require('../api')(config, function (err, api) {

    if (err) { return process.exit(0); }

    var setupFile = program.setup;

    if (setupFile) {

      var setup;

      setupFile = path.resolve('.', setupFile);

      try {
        setup = require(setupFile);
      } catch(ex) {
        console.log('Cant open setup file: ' + ex.message);
        process.exit(1);
      }

      console.log('Setting up seguir based on: ' + setupFile);
      api.client.setup.setupSeguir(api.client, setup.keyspace, function () {
        setupAccount(setup.account, function (err, account) {
          if (err) return error(err);
          setupAccountUser(account.account, setup.account, setup.user, setup.password, setup.admin, function (err, user) {
            if (err) return error(err);
            setupApplication(account.account, setup.application, setup.appid, setup.appsecret, function () {
              process.exit(0);
            });
          });
        });
      });

    } else {

      var tasks = {
        '[setup]   Check current setup': checkSetup,
        '[setup]   Initialise a new database instance': coreSetup,
        '[setup]   Add a new account, user and application': promptAccount,
        '[migrate] Check and apply database migrations': migration,
        '[account] List users for account': listUsers,
        '[account] Add a new user to an account': addUser,
        '[apps]    List applications for account': listApplications,
        '[apps]    Add a new application to an account': addApplication,
        '[tokens]  List application tokens': listTokens,
        '[tokens]  Add a token to an application': addToken,
        '[tokens]  Reset application token': resetApplicationToken,
        '[tokens]  Enable / disable application token': disableApplicationToken
      };

      inquirer.prompt([
        {
          type: 'list',
          message: 'What would you like to do [DB: ' + database.green + ']:',
          name: 'task',
          choices: _.keys(tasks)
        }
      ], function (answer) {
        tasks[answer.task]();
      });

    }

    function checkSetup () {
      // Check that the DB exists
      console.log('Checking ' + api.client.type + ': ' + JSON.stringify(config[api.client.type]));
      api.auth.getAccounts(function (err, accounts) {
        if (err) {
          console.log('An error was encountered: ' + err.message);
          if (err.message === 'Keyspace / schema seguir does not exist') {
            console.log('It looks like you need to initialise this instance, please re-run this command and select that option.');
          }
        } else {
          if (accounts.length === 0) {
            console.log('It looks like you need to create your first account, please re-run this command and select that option.');
          } else {
            console.log('Configuration looks OK on the surface, ' + accounts.length + ' accounts were found.');
          }
        }
        process.exit();
      });
    }

    function migration () {
      api.migrations.getMigrationsToApply(function (err, migrations) {
        if (err) return error(err);
        if (migrations.length === 0) {
          console.log('No database migrations to apply - everything is up to date.');
          return process.exit();
        }
        console.log('\nMigrations to apply:\n');
        migrations.forEach(function (migration) {
          console.log(migration.type.green + '[' + migration.keyspace.cyan + ']: ' + migration.version + ' ' + migration.description);
        });
        console.log('');
        confirmMigration(migrations);
      });
    }

    function confirmMigration (migrations) {
      inquirer.prompt([
        {
          type: 'confirm',
          message: 'Do you want to apply these migrations now?',
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.migrations.applyMigrations(migrations, function (err) {
            console.dir(err);
            if (err) return error(err);
            console.log('Database migrations complete.');
            process.exit();
          });
        } else {
          process.exit();
        }
      });
    }

    function listUsers () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        console.log(name + ' users:');
        api.auth.getAccountUsers(account, function (err, users) {
          if (err) return error(err);
          if (users) {
            users.forEach(function (user) {
              console.log(' - ' + user.username);
            });
          } else {
            console.log(' > No users for this account!');
          }
          process.exit();
        });
      });
    }

    function listApplications () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        console.log(name + ' applications:');
        api.auth.getApplications(account, function (err, apps) {
          if (err) return error(err);
          if (apps) {
            apps.forEach(function (app) {
              console.log(' - [' + app.name + '] appid: ' + app.appid);
            });
          } else {
            console.log(' > No apps for this account!');
          }
          process.exit();
        });
      });
    }

    function addToken () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        selectApplication(account, function (err, application, name, appkeyspace) {
          if (err) return error(err);
          inquirer.prompt([
            {
              type: 'input',
              message: 'Enter a token description:',
              name: 'description'
            }
          ], function (output) {
            if (!output.description) { return; }
            api.auth.addApplicationToken(application, appkeyspace, output.description, function (err, token) {
              if (err) return error(err);
              if (token) {
                console.log(' Added token: ' + output.description);
                console.log(' - tokenid: ' + token.tokenid + ' / tokensecret: ' + token.tokensecret);
              }
              process.exit();
            });
          });

        });
      });
    }

    function listTokens () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        selectApplication(account, function (err, application, name) {
          if (err) return error(err);
          console.log(name + ' applications:');
          api.auth.getApplicationTokens(application, function (err, tokens) {
            if (err) return error(err);
            if (tokens) {
              tokens.forEach(function (token) {
                console.log(' - [' + token.description + ' - ' + (token.enabled ? 'ENABLED' : 'DISABLED') + '] - tokenid: ' + token.tokenid + ' / tokensecret: ' + token.tokensecret);
              });
            } else {
              console.log(' > No tokens for this account!');
            }
            process.exit();
          });
        });
      });
    }

    function promptToken (next) {
      selectAccount(function (err, account) {
        if (err) return error(err);
        selectApplication(account, function (err, application) {
          if (err) return error(err);
          selectApplicationToken(application, function (err, token) {
            if (err) return error(err);
            next(null, token);
          });
        });
      });
    }

    function resetApplicationToken () {
      promptToken(function (err, token) {
        if (err) return error(err);
        confirmResetToken(token);
      });
    }

    function disableApplicationToken () {
      promptToken(function (err, token) {
        if (err) return error(err);
        confirmDisableToken(token);
      });
    }

    function selectAccount (next) {
      api.auth.getAccounts(function (err, accounts) {
        if (err) return error(err);
        var accs = _.pluck(accounts, 'name');
        inquirer.prompt([
          {
            type: 'list',
            message: 'Select an account:',
            name: 'name',
            choices: accs
          }
        ], function (answer) {
          next(null, _.result(_.find(accounts, { 'name': answer.name }), 'account'), answer.name);
        });
      });
    }

    function selectApplication (account, next) {
      api.auth.getApplications(account, function (err, applications) {
        if (err) return error(err);
        var apps = _.pluck(applications, 'name');
        inquirer.prompt([
          {
            type: 'list',
            message: 'Select an application:',
            name: 'name',
            choices: apps
          }
        ], function (answer) {
          var application = _.find(applications, { 'name': answer.name });
          next(null, _.result(application, 'appid'), answer.name, _.result(application, 'appkeyspace'));
        });
      });
    }

    function selectApplicationToken (application, next) {
      api.auth.getApplicationTokens(application, function (err, tokens) {
        if (err) return error(err);
        var tokenDescriptions = _.pluck(tokens, 'description');
        inquirer.prompt([
          {
            type: 'list',
            message: 'Select an application token:',
            name: 'description',
            choices: tokenDescriptions
          }
        ], function (answer) {
          var token = _.find(tokens, { 'description': answer.description });
          next(null, token);
        });
      });
    }

    function confirmResetToken (token) {
      inquirer.prompt([
        {
          type: 'confirm',
          message: 'This will modify the tokensecret so that the consumer using that token can no longer access seguir?',
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.auth.updateApplicationTokenSecret(token.tokenid, function (err, token) {
            if (!err) {
              console.log('Token updated, update the client application if you still want it to have access!');
              console.log('tokenid:     ' + token.tokenid);
              console.log('tokensecret: ' + token.tokensecret);
            } else {
              console.log('ERROR: ' + err.message);
            }
            process.exit();
          });
        } else {
          process.exit();
        }
      });
    }

    function confirmDisableToken (token) {
      var message = token.enabled ? 'This will disable a token so that any applications using it can no longer access seguir - they will immediately stop working - continue?' : 'Re-enable token?';
      inquirer.prompt([
        {
          type: 'confirm',
          message: message,
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.auth.updateApplicationToken(token.tokenid, !token.enabled, token.description, function (err, token) {
            if (!err) {
              console.log('Token is now: ' + (token.enabled ? 'ENABLED' : 'DISABLED'));
            } else {
              console.log('ERROR: ' + err.message);
            }
            process.exit();
          });
        } else {
          process.exit();
        }
      });
    }

    function coreSetup () {
      inquirer.prompt([
        {
          type: 'confirm',
          message: 'This will DROP the existing keyspace if it already exists, are you sure you want to proceed?',
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.client.setup.setupSeguir(api.client, config.keyspace, function () {
            console.log('Completed basic setup, you now need to create your first account and application.');
            promptAccount();
          });
        }
      });
    }

    function addUser () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        promptAccountUser(account, name, function (err) {
          if (err) return error(err);
          process.exit(0);
        });
      });
    }

    function addApplication () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        promptApplication(account, name, function (err) {
          if (err) return error(err);
          process.exit(0);
        });
      });
    }

    function promptAccount () {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter an account name:',
          name: 'name'
        }
      ], function (acc) {
        setupAccount(acc.name, function (err, account) {
          if (err) return error(err);
          promptAccountUser(account.account, account.name, function (err) {
            if (err) return error(err);
            promptApplication(account.account, account.name, function (err, application) {
              if (err) return error(err);
              process.exit(0);
            });
          });
        });
      });
    }

    function setupAccount (accName, next) {
      api.auth.addAccount(accName, true, true, function (err, account) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        next(null, account);
      });
    }

    function promptAccountUser (account, name, next) {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter name of user to add to account ' + name + ':',
          name: 'username'
        },
        {
          type: 'input',
          message: 'Enter password for this user:',
          name: 'password'
        },
        {
          type: 'input',
          message: 'Are they an administrator of the account (y/n)?',
          name: 'isadmin'
        }
      ], function (user) {
        setupAccountUser(account, name, user.username, user.password, user.isadmin === 'y', next);
      });
    }

    function setupAccountUser (account, name, username, password, isadmin, next) {
      api.auth.addAccountUser(account, username, password, isadmin, function (err, user) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        next();
      });
    }

    function promptApplication (account, name, next) {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter application name (e.g. app-name) to add to account ' + name + ':',
          name: 'name'
        }
      ], function (application) {
        setupApplication(account, application.name, null, null, next);
      });
    }

    function promptApplicationToken (application, next) {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter application token description (e.g. first-consumer) to add to application ' + application.name + ':',
          name: 'name'
        }
      ], function (token) {
        setupApplicationToken(application, token.name, next);
      });
    }

    function setupApplication (account, name, appid, appsecret, next) {
      console.log(' ... creating schema ...');
      api.auth.addApplication(account, name, appid, function (err, application) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        promptApplicationToken(application, next);
      });
    }

    function setupApplicationToken (application, name, next) {
      api.auth.addApplicationToken(application.appid, application.appkeypsace, name, function (err, token) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        console.log('Token details are:');
        console.log('description: ' + token.description);
        console.log('tokenid: ' + token.tokenid);
        console.log('tokensecret: ' + token.tokensecret);
        next();
      });
    }

  });

});
<commit_msg>Update CLI to work with setup scripts again<commit_after>#!/usr/bin/env node

/**
 * Command line client for seguir - used to setup a server.
 */
var inquirer = require('inquirer');
var program = require('commander');
var _ = require('lodash');
var path = require('path');

program
  .version('0.0.1')
  .option('-s, --setup [file]', 'Use setup file')
  .option('-c, --config [file]', 'Use config file')
  .option('-d, --database [database]', 'Use database type cassandra|postgres')
  .parse(process.argv);

var database = program.database || 'cassandra';
var defaultConfig = '../server/config/' + database;
var configFn;

if (program.config) {
  var configFile = path.resolve('.', program.config);
  try {
    configFn = require(configFile);
  } catch(ex) {
    console.log('Cant open config: ' + ex.message);
    process.exit(1);
  }
} else {
  var originalConfig = require(defaultConfig);
  configFn = function (next) {
    next(null, originalConfig);
  };
}

function error (err) {
  console.log('Error: ' + err.message);
  process.exit(1);
}

// Async load config
configFn(function (err, config) {

  if (err) return error(err);

  require('../api')(config, function (err, api) {

    if (err) { return process.exit(0); }

    var setupFile = program.setup;

    if (setupFile) {

      var setup;

      setupFile = path.resolve('.', setupFile);

      try {
        setup = require(setupFile);
      } catch(ex) {
        console.log('Cant open setup file: ' + ex.message);
        process.exit(1);
      }

      console.log('Setting up seguir based on: ' + setupFile);
      api.client.setup.setupSeguir(api.client, setup.keyspace, function () {
        setupAccount(setup.account, function (err, account) {
          if (err) return error(err);
          setupAccountUser(account.account, setup.account, setup.user, setup.password, setup.admin, function (err, user) {
            if (err) return error(err);
            setupApplication(account.account, setup.application, true, function (err, application) {
              if (err) return error(err);
              setupApplicationToken(application, setup.application, setup.appid, setup.appsecret, function (err) {
                if (err) return error(err);
                process.exit(0);
              });
            });
          });
        });
      });

    } else {

      var tasks = {
        '[setup]   Check current setup': checkSetup,
        '[setup]   Initialise a new database instance': coreSetup,
        '[setup]   Add a new account, user and application': promptAccount,
        '[migrate] Check and apply database migrations': migration,
        '[account] List users for account': listUsers,
        '[account] Add a new user to an account': addUser,
        '[apps]    List applications for account': listApplications,
        '[apps]    Add a new application to an account': addApplication,
        '[tokens]  List application tokens': listTokens,
        '[tokens]  Add a token to an application': addToken,
        '[tokens]  Reset application token': resetApplicationToken,
        '[tokens]  Enable / disable application token': disableApplicationToken
      };

      inquirer.prompt([
        {
          type: 'list',
          message: 'What would you like to do [DB: ' + database.green + ']:',
          name: 'task',
          choices: _.keys(tasks)
        }
      ], function (answer) {
        tasks[answer.task]();
      });

    }

    function checkSetup () {
      // Check that the DB exists
      console.log('Checking ' + api.client.type + ': ' + JSON.stringify(config[api.client.type]));
      api.auth.getAccounts(function (err, accounts) {
        if (err) {
          console.log('An error was encountered: ' + err.message);
          if (err.message === 'Keyspace / schema seguir does not exist') {
            console.log('It looks like you need to initialise this instance, please re-run this command and select that option.');
          }
        } else {
          if (accounts.length === 0) {
            console.log('It looks like you need to create your first account, please re-run this command and select that option.');
          } else {
            console.log('Configuration looks OK on the surface, ' + accounts.length + ' accounts were found.');
          }
        }
        process.exit();
      });
    }

    function migration () {
      api.migrations.getMigrationsToApply(function (err, migrations) {
        if (err) return error(err);
        if (migrations.length === 0) {
          console.log('No database migrations to apply - everything is up to date.');
          return process.exit();
        }
        console.log('\nMigrations to apply:\n');
        migrations.forEach(function (migration) {
          console.log(migration.type.green + '[' + migration.keyspace.cyan + ']: ' + migration.version + ' ' + migration.description);
        });
        console.log('');
        confirmMigration(migrations);
      });
    }

    function confirmMigration (migrations) {
      inquirer.prompt([
        {
          type: 'confirm',
          message: 'Do you want to apply these migrations now?',
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.migrations.applyMigrations(migrations, function (err) {
            console.dir(err);
            if (err) return error(err);
            console.log('Database migrations complete.');
            process.exit();
          });
        } else {
          process.exit();
        }
      });
    }

    function listUsers () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        console.log(name + ' users:');
        api.auth.getAccountUsers(account, function (err, users) {
          if (err) return error(err);
          if (users) {
            users.forEach(function (user) {
              console.log(' - ' + user.username);
            });
          } else {
            console.log(' > No users for this account!');
          }
          process.exit();
        });
      });
    }

    function listApplications () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        console.log(name + ' applications:');
        api.auth.getApplications(account, function (err, apps) {
          if (err) return error(err);
          if (apps) {
            apps.forEach(function (app) {
              console.log(' - [' + app.name + '] appid: ' + app.appid);
            });
          } else {
            console.log(' > No apps for this account!');
          }
          process.exit();
        });
      });
    }

    function addToken () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        selectApplication(account, function (err, application, name, appkeyspace) {
          if (err) return error(err);
          inquirer.prompt([
            {
              type: 'input',
              message: 'Enter a token description:',
              name: 'description'
            }
          ], function (output) {
            if (!output.description) { return; }
            api.auth.addApplicationToken(application, appkeyspace, output.description, function (err, token) {
              if (err) return error(err);
              if (token) {
                console.log(' Added token: ' + output.description);
                console.log(' - tokenid: ' + token.tokenid + ' / tokensecret: ' + token.tokensecret);
              }
              process.exit();
            });
          });

        });
      });
    }

    function listTokens () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        selectApplication(account, function (err, application, name) {
          if (err) return error(err);
          console.log(name + ' applications:');
          api.auth.getApplicationTokens(application, function (err, tokens) {
            if (err) return error(err);
            if (tokens) {
              tokens.forEach(function (token) {
                console.log(' - [' + token.description + ' - ' + (token.enabled ? 'ENABLED' : 'DISABLED') + '] - tokenid: ' + token.tokenid + ' / tokensecret: ' + token.tokensecret);
              });
            } else {
              console.log(' > No tokens for this account!');
            }
            process.exit();
          });
        });
      });
    }

    function promptToken (next) {
      selectAccount(function (err, account) {
        if (err) return error(err);
        selectApplication(account, function (err, application) {
          if (err) return error(err);
          selectApplicationToken(application, function (err, token) {
            if (err) return error(err);
            next(null, token);
          });
        });
      });
    }

    function resetApplicationToken () {
      promptToken(function (err, token) {
        if (err) return error(err);
        confirmResetToken(token);
      });
    }

    function disableApplicationToken () {
      promptToken(function (err, token) {
        if (err) return error(err);
        confirmDisableToken(token);
      });
    }

    function selectAccount (next) {
      api.auth.getAccounts(function (err, accounts) {
        if (err) return error(err);
        var accs = _.pluck(accounts, 'name');
        inquirer.prompt([
          {
            type: 'list',
            message: 'Select an account:',
            name: 'name',
            choices: accs
          }
        ], function (answer) {
          next(null, _.result(_.find(accounts, { 'name': answer.name }), 'account'), answer.name);
        });
      });
    }

    function selectApplication (account, next) {
      api.auth.getApplications(account, function (err, applications) {
        if (err) return error(err);
        var apps = _.pluck(applications, 'name');
        inquirer.prompt([
          {
            type: 'list',
            message: 'Select an application:',
            name: 'name',
            choices: apps
          }
        ], function (answer) {
          var application = _.find(applications, { 'name': answer.name });
          next(null, _.result(application, 'appid'), answer.name, _.result(application, 'appkeyspace'));
        });
      });
    }

    function selectApplicationToken (application, next) {
      api.auth.getApplicationTokens(application, function (err, tokens) {
        if (err) return error(err);
        var tokenDescriptions = _.pluck(tokens, 'description');
        inquirer.prompt([
          {
            type: 'list',
            message: 'Select an application token:',
            name: 'description',
            choices: tokenDescriptions
          }
        ], function (answer) {
          var token = _.find(tokens, { 'description': answer.description });
          next(null, token);
        });
      });
    }

    function confirmResetToken (token) {
      inquirer.prompt([
        {
          type: 'confirm',
          message: 'This will modify the tokensecret so that the consumer using that token can no longer access seguir?',
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.auth.updateApplicationTokenSecret(token.tokenid, function (err, token) {
            if (!err) {
              console.log('Token updated, update the client application if you still want it to have access!');
              console.log('tokenid:     ' + token.tokenid);
              console.log('tokensecret: ' + token.tokensecret);
            } else {
              console.log('ERROR: ' + err.message);
            }
            process.exit();
          });
        } else {
          process.exit();
        }
      });
    }

    function confirmDisableToken (token) {
      var message = token.enabled ? 'This will disable a token so that any applications using it can no longer access seguir - they will immediately stop working - continue?' : 'Re-enable token?';
      inquirer.prompt([
        {
          type: 'confirm',
          message: message,
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.auth.updateApplicationToken(token.tokenid, !token.enabled, token.description, function (err, token) {
            if (!err) {
              console.log('Token is now: ' + (token.enabled ? 'ENABLED' : 'DISABLED'));
            } else {
              console.log('ERROR: ' + err.message);
            }
            process.exit();
          });
        } else {
          process.exit();
        }
      });
    }

    function coreSetup () {
      inquirer.prompt([
        {
          type: 'confirm',
          message: 'This will DROP the existing keyspace if it already exists, are you sure you want to proceed?',
          name: 'confirm'
        }
      ], function (confirm) {
        if (confirm.confirm) {
          api.client.setup.setupSeguir(api.client, config.keyspace, function () {
            console.log('Completed basic setup, you now need to create your first account and application.');
            promptAccount();
          });
        }
      });
    }

    function addUser () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        promptAccountUser(account, name, function (err) {
          if (err) return error(err);
          process.exit(0);
        });
      });
    }

    function addApplication () {
      selectAccount(function (err, account, name) {
        if (err) return error(err);
        promptApplication(account, name, function (err) {
          if (err) return error(err);
          process.exit(0);
        });
      });
    }

    function promptAccount () {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter an account name:',
          name: 'name'
        }
      ], function (acc) {
        setupAccount(acc.name, function (err, account) {
          if (err) return error(err);
          promptAccountUser(account.account, account.name, function (err) {
            if (err) return error(err);
            promptApplication(account.account, account.name, function (err, application) {
              if (err) return error(err);
              process.exit(0);
            });
          });
        });
      });
    }

    function setupAccount (accName, next) {
      api.auth.addAccount(accName, true, true, function (err, account) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        next(null, account);
      });
    }

    function promptAccountUser (account, name, next) {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter name of user to add to account ' + name + ':',
          name: 'username'
        },
        {
          type: 'input',
          message: 'Enter password for this user:',
          name: 'password'
        },
        {
          type: 'input',
          message: 'Are they an administrator of the account (y/n)?',
          name: 'isadmin'
        }
      ], function (user) {
        setupAccountUser(account, name, user.username, user.password, user.isadmin === 'y', next);
      });
    }

    function setupAccountUser (account, name, username, password, isadmin, next) {
      api.auth.addAccountUser(account, username, password, isadmin, function (err, user) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        next();
      });
    }

    function promptApplication (account, name, next) {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter application name (e.g. app-name) to add to account ' + name + ':',
          name: 'name'
        }
      ], function (application) {
        setupApplication(account, application.name, next);
      });
    }

    function promptApplicationToken (application, next) {
      inquirer.prompt([
        {
          type: 'input',
          message: 'Enter application token description (e.g. first-consumer) to add to application ' + application.name + ':',
          name: 'name'
        }
      ], function (token) {
        setupApplicationToken(application, token.name, next);
      });
    }

    function setupApplication (account, name, noToken, next) {
      if (!next) { next = noToken; noToken = false; }
      console.log(' ... creating schema ...');
      api.auth.addApplication(account, name, function (err, application) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        if (noToken) return next(null, application);
        promptApplicationToken(application, next);
      });
    }

    function setupApplicationToken (application, name, tokenid, tokensecret, next) {
      if (!next) { next = tokensecret; tokensecret = null; }
      if (!next) { next = tokenid; tokenid = null; }
      api.auth.addApplicationToken(application.appid, application.appkeypsace, name, tokenid, tokensecret, function (err, token) {
        if (err) {
          console.log(err.message);
          process.exit(0);
        }
        console.log('Token details are:');
        console.log('description: ' + token.description);
        console.log('tokenid: ' + token.tokenid);
        console.log('tokensecret: ' + token.tokensecret);
        next();
      });
    }

  });

});
<|endoftext|>