<commit_before>const HashTable = require('ml-hash-table');

class SparseMatrix {
    constructor(rows, columns, options = {}) {
        if (rows instanceof SparseMatrix) { // clone
            const other = rows;
            this._init(other.rows, other.columns, other.elements.clone(), other.threshold);
            return;
        }

        if (Array.isArray(rows)) {
            const matrix = rows;
            rows = matrix.length;
            options = columns || {};
            columns = matrix[0].length;
            this._init(rows, columns, new HashTable(options), options.threshold);
            for (var i = 0; i < rows; i++) {
                for (var j = 0; j < columns; j++) {
                    var value = matrix[i][j];
                    if (this.threshold && Math.abs(value) < this.threshold) value = 0;
                    if (value !== 0) {
                        this.elements.set(i * columns + j, matrix[i][j]);
                    }
                }
            }
        } else {
            this._init(rows, columns, new HashTable(options), options.threshold);
        }
    }

    _init(rows, columns, elements, threshold) {
        this.rows = rows;
        this.columns = columns;
        this.elements = elements;
        this.threshold = threshold || 0;
    }

    static eye(rows = 1, columns = rows) {
        const min = Math.min(rows, columns);
        const matrix = new SparseMatrix(rows, columns, {initialCapacity: min});
        for (var i = 0; i < min; i++) {
            matrix.set(i, i, 1);
        }
        return matrix;
    }

    clone() {
        return new SparseMatrix(this);
    }

    to2DArray() {
        const copy = new Array(this.rows);
        for (var i = 0; i < this.rows; i++) {
            copy[i] = new Array(this.columns);
            for (var j = 0; j < this.columns; j++) {
                copy[i][j] = this.get(i, j);
            }
        }
        return copy;
    }

    isSquare() {
        return this.rows === this.columns;
    }

    isSymmetric() {
        if (!this.isSquare()) return false;

        var symmetric = true;
        this.forEachNonZero((i, j, v) => {
            if (this.get(j, i) !== v) {
                symmetric = false;
                return false;
            }
            return v;
        });
        return symmetric;
    }

    get cardinality() {
        return this.elements.size;
    }

    get size() {
        return this.rows * this.columns;
    }

    get(row, column) {
        return this.elements.get(row * this.columns + column);
    }

    set(row, column, value) {
        if (this.threshold && Math.abs(value) < this.threshold) value = 0;
        if (value === 0) {
            this.elements.remove(row * this.columns + column);
        } else {
            this.elements.set(row * this.columns + column, value);
        }
        return this;
    }

    mmul(other) {
        if (this.columns !== other.rows)
            console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.');

        const m = this.rows;
        const p = other.columns;

        const result = new SparseMatrix(m, p);
        this.forEachNonZero((i, j, v1) => {
            other.forEachNonZero((k, l, v2) => {
                if (j === k) {
                    result.set(i, l, result.get(i, l) + v1 * v2);
                }
                return v2;
            });
            return v1;
        });
        return result;
    }

    kroneckerProduct(other) {
        const m = this.rows;
        const n = this.columns;
        const p = other.rows;
        const q = other.columns;

        const result = new SparseMatrix(m * p, n * q, {
            initialCapacity: this.cardinality * other.cardinality
        });
        this.forEachNonZero((i, j, v1) => {
            other.forEachNonZero((k, l, v2) => {
                result.set(p * i + k, q * j + l, v1 * v2);
                return v2;
            });
            return v1;
        });
        return result;
    }

    forEachNonZero(callback) {
        return this.elements.forEachPair((key, value) => {
            const i = (key / this.columns) | 0;
            const j = key % this.columns;
            const r = callback(i, j, value);
            if (r === false) return false; // stop iteration
            if (r !== value) {
                if (r === 0) {
                    this.elements.remove(key);
                } else {
                    this.elements.set(key, r);
                }
            }
            return true;
        });
    }

    getNonZeros() {
        const cardinality = this.cardinality;
        const rows = new Array(cardinality);
        const columns = new Array(cardinality);
        const values = new Array(cardinality);
        var idx = 0;
        this.forEachNonZero((i, j, value) => {
            rows[idx] = i;
            columns[idx] = j;
            values[idx] = value;
            idx++;
            return value;
        });
        return {rows, columns, values};
    }
}

SparseMatrix.prototype.klass = 'Matrix';

SparseMatrix.identity = SparseMatrix.eye;
SparseMatrix.prototype.tensorProduct = SparseMatrix.prototype.kroneckerProduct;

module.exports = SparseMatrix;

/*
 Add dynamically instance and static methods for mathematical operations
 */

var inplaceOperator = `
(function %name%(value) {
    if (typeof value === 'number') return this.%name%S(value);
    return this.%name%M(value);
})
`;

var inplaceOperatorScalar = `
(function %name%S(value) {
    this.forEachNonZero((i, j, v) => v %op% value);
    return this;
})
`;

var inplaceOperatorMatrix = `
(function %name%M(matrix) {
    matrix.forEachNonZero((i, j, v) => {
        this.set(i, j, this.get(i, j) %op% v);
        return v;
    });
    return this;
})
`;

var staticOperator = `
(function %name%(matrix, value) {
    var newMatrix = new SparseMatrix(matrix);
    return newMatrix.%name%(value);
})
`;

var inplaceMethod = `
(function %name%() {
    this.forEachNonZero((i, j, v) => %method%(v));
    return this;
})
`;

var staticMethod = `
(function %name%(matrix) {
    var newMatrix = new SparseMatrix(matrix);
    return newMatrix.%name%();
})
`;

var operators = [
    // Arithmetic operators
    ['+', 'add'],
    ['-', 'sub', 'subtract'],
    ['*', 'mul', 'multiply'],
    ['/', 'div', 'divide'],
    ['%', 'mod', 'modulus'],
    // Bitwise operators
    ['&', 'and'],
    ['|', 'or'],
    ['^', 'xor'],
    ['<<', 'leftShift'],
    ['>>', 'signPropagatingRightShift'],
    ['>>>', 'rightShift', 'zeroFillRightShift']
];

for (var operator of operators) {
    for (var i = 1; i < operator.length; i++) {
        SparseMatrix.prototype[operator[i]] = eval(fillTemplateFunction(inplaceOperator, {name: operator[i], op: operator[0]}));
        SparseMatrix.prototype[operator[i] + 'S'] = eval(fillTemplateFunction(inplaceOperatorScalar, {name: operator[i] + 'S', op: operator[0]}));
        SparseMatrix.prototype[operator[i] + 'M'] = eval(fillTemplateFunction(inplaceOperatorMatrix, {name: operator[i] + 'M', op: operator[0]}));

        SparseMatrix[operator[i]] = eval(fillTemplateFunction(staticOperator, {name: operator[i]}));
    }
}

var methods = [
    ['~', 'not']
];

[
    'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cbrt', 'ceil',
    'clz32', 'cos', 'cosh', 'exp', 'expm1', 'floor', 'fround', 'log', 'log1p',
    'log10', 'log2', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc'
].forEach(function (mathMethod) {
    methods.push(['Math.' + mathMethod, mathMethod]);
});

for (var method of methods) {
    for (var i = 1; i < method.length; i++) {
        SparseMatrix.prototype[method[i]] = eval(fillTemplateFunction(inplaceMethod, {name: method[i], method: method[0]}));
        SparseMatrix[method[i]] = eval(fillTemplateFunction(staticMethod, {name: method[i]}));
    }
}

function fillTemplateFunction(template, values) {
    for (var i in values) {
        template = template.replace(new RegExp('%' + i + '%', 'g'), values[i]);
    }
    return template;
}
<commit_msg>add setThreshold<commit_after>const HashTable = require('ml-hash-table');

class SparseMatrix {
    constructor(rows, columns, options = {}) {
        if (rows instanceof SparseMatrix) { // clone
            const other = rows;
            this._init(other.rows, other.columns, other.elements.clone(), other.threshold);
            return;
        }

        if (Array.isArray(rows)) {
            const matrix = rows;
            rows = matrix.length;
            options = columns || {};
            columns = matrix[0].length;
            this._init(rows, columns, new HashTable(options), options.threshold);
            for (var i = 0; i < rows; i++) {
                for (var j = 0; j < columns; j++) {
                    var value = matrix[i][j];
                    if (this.threshold && Math.abs(value) < this.threshold) value = 0;
                    if (value !== 0) {
                        this.elements.set(i * columns + j, matrix[i][j]);
                    }
                }
            }
        } else {
            this._init(rows, columns, new HashTable(options), options.threshold);
        }
    }

    _init(rows, columns, elements, threshold) {
        this.rows = rows;
        this.columns = columns;
        this.elements = elements;
        this.threshold = threshold || 0;
    }

    static eye(rows = 1, columns = rows) {
        const min = Math.min(rows, columns);
        const matrix = new SparseMatrix(rows, columns, {initialCapacity: min});
        for (var i = 0; i < min; i++) {
            matrix.set(i, i, 1);
        }
        return matrix;
    }

    clone() {
        return new SparseMatrix(this);
    }

    to2DArray() {
        const copy = new Array(this.rows);
        for (var i = 0; i < this.rows; i++) {
            copy[i] = new Array(this.columns);
            for (var j = 0; j < this.columns; j++) {
                copy[i][j] = this.get(i, j);
            }
        }
        return copy;
    }

    isSquare() {
        return this.rows === this.columns;
    }

    isSymmetric() {
        if (!this.isSquare()) return false;

        var symmetric = true;
        this.forEachNonZero((i, j, v) => {
            if (this.get(j, i) !== v) {
                symmetric = false;
                return false;
            }
            return v;
        });
        return symmetric;
    }

    get cardinality() {
        return this.elements.size;
    }

    get size() {
        return this.rows * this.columns;
    }

    get(row, column) {
        return this.elements.get(row * this.columns + column);
    }

    set(row, column, value) {
        if (this.threshold && Math.abs(value) < this.threshold) value = 0;
        if (value === 0) {
            this.elements.remove(row * this.columns + column);
        } else {
            this.elements.set(row * this.columns + column, value);
        }
        return this;
    }

    mmul(other) {
        if (this.columns !== other.rows)
            console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.');

        const m = this.rows;
        const p = other.columns;

        const result = new SparseMatrix(m, p);
        this.forEachNonZero((i, j, v1) => {
            other.forEachNonZero((k, l, v2) => {
                if (j === k) {
                    result.set(i, l, result.get(i, l) + v1 * v2);
                }
                return v2;
            });
            return v1;
        });
        return result;
    }

    kroneckerProduct(other) {
        const m = this.rows;
        const n = this.columns;
        const p = other.rows;
        const q = other.columns;

        const result = new SparseMatrix(m * p, n * q, {
            initialCapacity: this.cardinality * other.cardinality
        });
        this.forEachNonZero((i, j, v1) => {
            other.forEachNonZero((k, l, v2) => {
                result.set(p * i + k, q * j + l, v1 * v2);
                return v2;
            });
            return v1;
        });
        return result;
    }

    forEachNonZero(callback) {
        this.elements.forEachPair((key, value) => {
            const i = (key / this.columns) | 0;
            const j = key % this.columns;
            let r = callback(i, j, value);
            if (r === false) return false; // stop iteration
            if (this.threshold && Math.abs(r) < this.threshold) r = 0;
            if (r !== value) {
                if (r === 0) {
                    this.elements.remove(key);
                } else {
                    this.elements.set(key, r);
                }
            }
            return true;
        });
        return this;
    }

    getNonZeros() {
        const cardinality = this.cardinality;
        const rows = new Array(cardinality);
        const columns = new Array(cardinality);
        const values = new Array(cardinality);
        var idx = 0;
        this.forEachNonZero((i, j, value) => {
            rows[idx] = i;
            columns[idx] = j;
            values[idx] = value;
            idx++;
            return value;
        });
        return {rows, columns, values};
    }

    setThreshold(newThreshold) {
        if (newThreshold !== 0 && newThreshold !== this.threshold) {
            this.threshold = newThreshold;
            this.forEachNonZero((i, j, v) => v);
        }
        return this;
    }
}

SparseMatrix.prototype.klass = 'Matrix';

SparseMatrix.identity = SparseMatrix.eye;
SparseMatrix.prototype.tensorProduct = SparseMatrix.prototype.kroneckerProduct;

module.exports = SparseMatrix;

/*
 Add dynamically instance and static methods for mathematical operations
 */

var inplaceOperator = `
(function %name%(value) {
    if (typeof value === 'number') return this.%name%S(value);
    return this.%name%M(value);
})
`;

var inplaceOperatorScalar = `
(function %name%S(value) {
    this.forEachNonZero((i, j, v) => v %op% value);
    return this;
})
`;

var inplaceOperatorMatrix = `
(function %name%M(matrix) {
    matrix.forEachNonZero((i, j, v) => {
        this.set(i, j, this.get(i, j) %op% v);
        return v;
    });
    return this;
})
`;

var staticOperator = `
(function %name%(matrix, value) {
    var newMatrix = new SparseMatrix(matrix);
    return newMatrix.%name%(value);
})
`;

var inplaceMethod = `
(function %name%() {
    this.forEachNonZero((i, j, v) => %method%(v));
    return this;
})
`;

var staticMethod = `
(function %name%(matrix) {
    var newMatrix = new SparseMatrix(matrix);
    return newMatrix.%name%();
})
`;

var operators = [
    // Arithmetic operators
    ['+', 'add'],
    ['-', 'sub', 'subtract'],
    ['*', 'mul', 'multiply'],
    ['/', 'div', 'divide'],
    ['%', 'mod', 'modulus'],
    // Bitwise operators
    ['&', 'and'],
    ['|', 'or'],
    ['^', 'xor'],
    ['<<', 'leftShift'],
    ['>>', 'signPropagatingRightShift'],
    ['>>>', 'rightShift', 'zeroFillRightShift']
];

for (var operator of operators) {
    for (var i = 1; i < operator.length; i++) {
        SparseMatrix.prototype[operator[i]] = eval(fillTemplateFunction(inplaceOperator, {name: operator[i], op: operator[0]}));
        SparseMatrix.prototype[operator[i] + 'S'] = eval(fillTemplateFunction(inplaceOperatorScalar, {name: operator[i] + 'S', op: operator[0]}));
        SparseMatrix.prototype[operator[i] + 'M'] = eval(fillTemplateFunction(inplaceOperatorMatrix, {name: operator[i] + 'M', op: operator[0]}));

        SparseMatrix[operator[i]] = eval(fillTemplateFunction(staticOperator, {name: operator[i]}));
    }
}

var methods = [
    ['~', 'not']
];

[
    'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cbrt', 'ceil',
    'clz32', 'cos', 'cosh', 'exp', 'expm1', 'floor', 'fround', 'log', 'log1p',
    'log10', 'log2', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc'
].forEach(function (mathMethod) {
    methods.push(['Math.' + mathMethod, mathMethod]);
});

for (var method of methods) {
    for (var i = 1; i < method.length; i++) {
        SparseMatrix.prototype[method[i]] = eval(fillTemplateFunction(inplaceMethod, {name: method[i], method: method[0]}));
        SparseMatrix[method[i]] = eval(fillTemplateFunction(staticMethod, {name: method[i]}));
    }
}

function fillTemplateFunction(template, values) {
    for (var i in values) {
        template = template.replace(new RegExp('%' + i + '%', 'g'), values[i]);
    }
    return template;
}
<|endoftext|>


<commit_before>/*global define*/
define([
        '../Core/BoundingRectangle',
        '../Core/BoundingSphere',
        '../Core/Cartesian2',
        '../Core/Cartesian3',
        '../Core/Cartesian4',
        '../Core/Color',
        '../Core/ComponentDatatype',
        '../Core/defined',
        '../Core/defineProperties',
        '../Core/destroyObject',
        '../Core/IndexDatatype',
        '../Core/Math',
        '../Core/Matrix4',
        '../Core/PixelFormat',
        '../Core/PrimitiveType',
        '../Renderer/Buffer',
        '../Renderer/BufferUsage',
        '../Renderer/ClearCommand',
        '../Renderer/ComputeCommand',
        '../Renderer/DrawCommand',
        '../Renderer/Framebuffer',
        '../Renderer/RenderState',
        '../Renderer/ShaderProgram',
        '../Renderer/Texture',
        '../Renderer/VertexArray',
        '../Shaders/SunFS',
        '../Shaders/SunTextureFS',
        '../Shaders/SunVS',
        './BlendingState',
        './SceneMode',
        './SceneTransforms'
    ], function(
        BoundingRectangle,
        BoundingSphere,
        Cartesian2,
        Cartesian3,
        Cartesian4,
        Color,
        ComponentDatatype,
        defined,
        defineProperties,
        destroyObject,
        IndexDatatype,
        CesiumMath,
        Matrix4,
        PixelFormat,
        PrimitiveType,
        Buffer,
        BufferUsage,
        ClearCommand,
        ComputeCommand,
        DrawCommand,
        Framebuffer,
        RenderState,
        ShaderProgram,
        Texture,
        VertexArray,
        SunFS,
        SunTextureFS,
        SunVS,
        BlendingState,
        SceneMode,
        SceneTransforms) {
    "use strict";

    /**
     * Draws a sun billboard.
     *
This is only supported in 3D and Columbus view.

     *
     * @alias Sun
     * @constructor
     *
     * @see Scene#sun
     *
     * @example
     * scene.sun = new Cesium.Sun();
     */
    var Sun = function() {
        /**
         * Determines if the sun will be shown.
         *
         * @type {Boolean}
         * @default true
         */
        this.show = true;

        this._drawCommand = new DrawCommand({
            primitiveType : PrimitiveType.TRIANGLES,
            boundingVolume : new BoundingSphere(),
            owner : this
        });
        this._commands = {
            drawCommand : this._drawCommand,
            computeCommand : undefined
        };
        this._boundingVolume = new BoundingSphere();
        this._boundingVolume2D = new BoundingSphere();

        this._texture = undefined;
        this._drawingBufferWidth = undefined;
        this._drawingBufferHeight = undefined;
        this._radiusTS = undefined;
        this._size = undefined;

        this.glowFactor = 1.0;
        this._glowFactorDirty = false;

        var that = this;
        this._uniformMap = {
            u_texture : function() {
                return that._texture;
            },
            u_size : function() {
                return that._size;
            }
        };
    };

    defineProperties(Sun.prototype, {
        /**
         * Gets or sets a number that controls how "bright" the Sun's lens flare appears
         * to be.  Zero shows just the Sun's disc without any flare.
         * Use larger values for a more pronounced flare around the Sun.
         *
         * @memberof Sun.prototype
         * @type {Number}
         * @default 1.0
         */
        glowFactor : {
            get : function () { return this._glowFactor; },
            set : function (glowFactor) {
                glowFactor = Math.max(glowFactor, 0.0);
                this._glowFactor = glowFactor;
                this._glowFactorDirty = true;
            }
        }
    });

    var scratchPositionWC = new Cartesian2();
    var scratchLimbWC = new Cartesian2();
    var scratchPositionEC = new Cartesian4();
    var scratchCartesian4 = new Cartesian4();

    /**
     * @private
     */
    Sun.prototype.update = function(scene) {
        var frameState = scene.frameState;
        var context = scene.context;

        if (!this.show) {
            return undefined;
        }

        var mode = frameState.mode;
        if (mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) {
            return undefined;
        }

        if (!frameState.passes.render) {
            return undefined;
        }

        var drawingBufferWidth = scene.drawingBufferWidth;
        var drawingBufferHeight = scene.drawingBufferHeight;

        if (!defined(this._texture) ||
                drawingBufferWidth !== this._drawingBufferWidth ||
                drawingBufferHeight !== this._drawingBufferHeight ||
                this._glowFactorDirty) {
            this._texture = this._texture && this._texture.destroy();
            this._drawingBufferWidth = drawingBufferWidth;
            this._drawingBufferHeight = drawingBufferHeight;
            this._glowFactorDirty = false;

            var size = Math.max(drawingBufferWidth, drawingBufferHeight);
            size = Math.pow(2.0, Math.ceil(Math.log(size) / Math.log(2.0)) - 2.0);

            this._texture = new Texture({
                context : context,
                width : size,
                height : size,
                pixelFormat : PixelFormat.RGBA
            });

            this._glowLengthTS = this._glowFactor * 5.0;
            this._radiusTS = (1.0 / (1.0 + 2.0 * this._glowLengthTS)) * 0.5;

            var that = this;
            var uniformMap = {
                u_glowLengthTS : function() {
                    return that._glowLengthTS;
                },
                u_radiusTS : function() {
                    return that._radiusTS;
                }
            };

            this._commands.computeCommand = new ComputeCommand({
                fragmentShaderSource : SunTextureFS,
                outputTexture  : this._texture,
                persists : false,
                owner : this,
                postExecute : function() {
                    that._commands.computeCommand = undefined;
                }
            });
        }

        var drawCommand = this._drawCommand;

        if (!defined(drawCommand.vertexArray)) {
            var attributeLocations = {
                direction : 0
            };

            var directions = new Uint8Array(4 * 2);
            directions[0] = 0;
            directions[1] = 0;

            directions[2] = 255;
            directions[3] = 0.0;

            directions[4] = 255;
            directions[5] = 255;

            directions[6] = 0.0;
            directions[7] = 255;

            var vertexBuffer = Buffer.createVertexBuffer({
                context : context,
                typedArray : directions,
                usage : BufferUsage.STATIC_DRAW
            });
            var attributes = [{
                index : attributeLocations.direction,
                vertexBuffer : vertexBuffer,
                componentsPerAttribute : 2,
                normalize : true,
                componentDatatype : ComponentDatatype.UNSIGNED_BYTE
            }];
            // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
            var indexBuffer = Buffer.createIndexBuffer({
                context : context,
                typedArray : new Uint16Array([0, 1, 2, 0, 2, 3]),
                usage : BufferUsage.STATIC_DRAW,
                indexDatatype : IndexDatatype.UNSIGNED_SHORT
            });
            drawCommand.vertexArray = new VertexArray({
                context : context,
                attributes : attributes,
                indexBuffer : indexBuffer
            });

            drawCommand.shaderProgram = ShaderProgram.fromCache({
                context : context,
                vertexShaderSource : SunVS,
                fragmentShaderSource : SunFS,
                attributeLocations : attributeLocations
            });

            drawCommand.renderState = RenderState.fromCache({
                blending : BlendingState.ALPHA_BLEND
            });
            drawCommand.uniformMap = this._uniformMap;
        }

        var sunPosition = context.uniformState.sunPositionWC;
        var sunPositionCV = context.uniformState.sunPositionColumbusView;

        var boundingVolume = this._boundingVolume;
        var boundingVolume2D = this._boundingVolume2D;

        Cartesian3.clone(sunPosition, boundingVolume.center);
        boundingVolume2D.center.x = sunPositionCV.z;
        boundingVolume2D.center.y = sunPositionCV.x;
        boundingVolume2D.center.z = sunPositionCV.y;

        boundingVolume.radius = CesiumMath.SOLAR_RADIUS + CesiumMath.SOLAR_RADIUS * this._glowLengthTS;
        boundingVolume2D.radius = boundingVolume.radius;

        if (mode === SceneMode.SCENE3D) {
            BoundingSphere.clone(boundingVolume, drawCommand.boundingVolume);
        } else if (mode === SceneMode.COLUMBUS_VIEW) {
            BoundingSphere.clone(boundingVolume2D, drawCommand.boundingVolume);
        }

        var position = SceneTransforms.computeActualWgs84Position(frameState, sunPosition, scratchCartesian4);

        var dist = Cartesian3.magnitude(Cartesian3.subtract(position, scene.camera.position, scratchCartesian4));
        var projMatrix = context.uniformState.projection;

        var positionEC = scratchPositionEC;
        positionEC.x = 0;
        positionEC.y = 0;
        positionEC.z = -dist;
        positionEC.w = 1;

        var positionCC = Matrix4.multiplyByVector(projMatrix, positionEC, scratchCartesian4);
        var positionWC = SceneTransforms.clipToDrawingBufferCoordinates(scene, positionCC, scratchPositionWC);

        positionEC.x = CesiumMath.SOLAR_RADIUS;
        var limbCC = Matrix4.multiplyByVector(projMatrix, positionEC, scratchCartesian4);
        var limbWC = SceneTransforms.clipToDrawingBufferCoordinates(scene, limbCC, scratchLimbWC);

        this._size = Math.ceil(Cartesian2.magnitude(Cartesian2.subtract(limbWC, positionWC, scratchCartesian4)));
        this._size = 2.0 * this._size * (1.0 + 2.0 * this._glowLengthTS);

        return this._commands;
    };

    /**
     * Returns true if this object was destroyed; otherwise, false.
     *

     * If this object was destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.
     *
     * @returns {Boolean} true if this object was destroyed; otherwise, false.
     *
     * @see Sun#destroy
     */
    Sun.prototype.isDestroyed = function() {
        return false;
    };

    /**
     * Destroys the WebGL resources held by this object.  Destroying an object allows for deterministic
     * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
     *

     * Once an object is destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.  Therefore,
     * assign the return value (undefined) to the object as done in the example.
     *
     * @returns {undefined}
     *
     * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
     *
     * @see Sun#isDestroyed
     *
     * @example
     * sun = sun && sun.destroy();
     */
    Sun.prototype.destroy = function() {
        var command = this._drawCommand;
        command.vertexArray = command.vertexArray && command.vertexArray.destroy();
        command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();

        this._texture = this._texture && this._texture.destroy();

        return destroyObject(this);
    };

    return Sun;
});
<commit_msg>Fix sun uniform<commit_after>/*global define*/
define([
        '../Core/BoundingRectangle',
        '../Core/BoundingSphere',
        '../Core/Cartesian2',
        '../Core/Cartesian3',
        '../Core/Cartesian4',
        '../Core/Color',
        '../Core/ComponentDatatype',
        '../Core/defined',
        '../Core/defineProperties',
        '../Core/destroyObject',
        '../Core/IndexDatatype',
        '../Core/Math',
        '../Core/Matrix4',
        '../Core/PixelFormat',
        '../Core/PrimitiveType',
        '../Renderer/Buffer',
        '../Renderer/BufferUsage',
        '../Renderer/ClearCommand',
        '../Renderer/ComputeCommand',
        '../Renderer/DrawCommand',
        '../Renderer/Framebuffer',
        '../Renderer/RenderState',
        '../Renderer/ShaderProgram',
        '../Renderer/Texture',
        '../Renderer/VertexArray',
        '../Shaders/SunFS',
        '../Shaders/SunTextureFS',
        '../Shaders/SunVS',
        './BlendingState',
        './SceneMode',
        './SceneTransforms'
    ], function(
        BoundingRectangle,
        BoundingSphere,
        Cartesian2,
        Cartesian3,
        Cartesian4,
        Color,
        ComponentDatatype,
        defined,
        defineProperties,
        destroyObject,
        IndexDatatype,
        CesiumMath,
        Matrix4,
        PixelFormat,
        PrimitiveType,
        Buffer,
        BufferUsage,
        ClearCommand,
        ComputeCommand,
        DrawCommand,
        Framebuffer,
        RenderState,
        ShaderProgram,
        Texture,
        VertexArray,
        SunFS,
        SunTextureFS,
        SunVS,
        BlendingState,
        SceneMode,
        SceneTransforms) {
    "use strict";

    /**
     * Draws a sun billboard.
     *
This is only supported in 3D and Columbus view.

     *
     * @alias Sun
     * @constructor
     *
     * @see Scene#sun
     *
     * @example
     * scene.sun = new Cesium.Sun();
     */
    var Sun = function() {
        /**
         * Determines if the sun will be shown.
         *
         * @type {Boolean}
         * @default true
         */
        this.show = true;

        this._drawCommand = new DrawCommand({
            primitiveType : PrimitiveType.TRIANGLES,
            boundingVolume : new BoundingSphere(),
            owner : this
        });
        this._commands = {
            drawCommand : this._drawCommand,
            computeCommand : undefined
        };
        this._boundingVolume = new BoundingSphere();
        this._boundingVolume2D = new BoundingSphere();

        this._texture = undefined;
        this._drawingBufferWidth = undefined;
        this._drawingBufferHeight = undefined;
        this._radiusTS = undefined;
        this._size = undefined;

        this.glowFactor = 1.0;
        this._glowFactorDirty = false;

        var that = this;
        this._uniformMap = {
            u_texture : function() {
                return that._texture;
            },
            u_size : function() {
                return that._size;
            }
        };
    };

    defineProperties(Sun.prototype, {
        /**
         * Gets or sets a number that controls how "bright" the Sun's lens flare appears
         * to be.  Zero shows just the Sun's disc without any flare.
         * Use larger values for a more pronounced flare around the Sun.
         *
         * @memberof Sun.prototype
         * @type {Number}
         * @default 1.0
         */
        glowFactor : {
            get : function () { return this._glowFactor; },
            set : function (glowFactor) {
                glowFactor = Math.max(glowFactor, 0.0);
                this._glowFactor = glowFactor;
                this._glowFactorDirty = true;
            }
        }
    });

    var scratchPositionWC = new Cartesian2();
    var scratchLimbWC = new Cartesian2();
    var scratchPositionEC = new Cartesian4();
    var scratchCartesian4 = new Cartesian4();

    /**
     * @private
     */
    Sun.prototype.update = function(scene) {
        var frameState = scene.frameState;
        var context = scene.context;

        if (!this.show) {
            return undefined;
        }

        var mode = frameState.mode;
        if (mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) {
            return undefined;
        }

        if (!frameState.passes.render) {
            return undefined;
        }

        var drawingBufferWidth = scene.drawingBufferWidth;
        var drawingBufferHeight = scene.drawingBufferHeight;

        if (!defined(this._texture) ||
                drawingBufferWidth !== this._drawingBufferWidth ||
                drawingBufferHeight !== this._drawingBufferHeight ||
                this._glowFactorDirty) {
            this._texture = this._texture && this._texture.destroy();
            this._drawingBufferWidth = drawingBufferWidth;
            this._drawingBufferHeight = drawingBufferHeight;
            this._glowFactorDirty = false;

            var size = Math.max(drawingBufferWidth, drawingBufferHeight);
            size = Math.pow(2.0, Math.ceil(Math.log(size) / Math.log(2.0)) - 2.0);

            this._texture = new Texture({
                context : context,
                width : size,
                height : size,
                pixelFormat : PixelFormat.RGBA
            });

            this._glowLengthTS = this._glowFactor * 5.0;
            this._radiusTS = (1.0 / (1.0 + 2.0 * this._glowLengthTS)) * 0.5;

            var that = this;
            var uniformMap = {
                u_glowLengthTS : function() {
                    return that._glowLengthTS;
                },
                u_radiusTS : function() {
                    return that._radiusTS;
                }
            };

            this._commands.computeCommand = new ComputeCommand({
                fragmentShaderSource : SunTextureFS,
                outputTexture  : this._texture,
                uniformMap : uniformMap,
                persists : false,
                owner : this,
                postExecute : function() {
                    that._commands.computeCommand = undefined;
                }
            });
        }

        var drawCommand = this._drawCommand;

        if (!defined(drawCommand.vertexArray)) {
            var attributeLocations = {
                direction : 0
            };

            var directions = new Uint8Array(4 * 2);
            directions[0] = 0;
            directions[1] = 0;

            directions[2] = 255;
            directions[3] = 0.0;

            directions[4] = 255;
            directions[5] = 255;

            directions[6] = 0.0;
            directions[7] = 255;

            var vertexBuffer = Buffer.createVertexBuffer({
                context : context,
                typedArray : directions,
                usage : BufferUsage.STATIC_DRAW
            });
            var attributes = [{
                index : attributeLocations.direction,
                vertexBuffer : vertexBuffer,
                componentsPerAttribute : 2,
                normalize : true,
                componentDatatype : ComponentDatatype.UNSIGNED_BYTE
            }];
            // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
            var indexBuffer = Buffer.createIndexBuffer({
                context : context,
                typedArray : new Uint16Array([0, 1, 2, 0, 2, 3]),
                usage : BufferUsage.STATIC_DRAW,
                indexDatatype : IndexDatatype.UNSIGNED_SHORT
            });
            drawCommand.vertexArray = new VertexArray({
                context : context,
                attributes : attributes,
                indexBuffer : indexBuffer
            });

            drawCommand.shaderProgram = ShaderProgram.fromCache({
                context : context,
                vertexShaderSource : SunVS,
                fragmentShaderSource : SunFS,
                attributeLocations : attributeLocations
            });

            drawCommand.renderState = RenderState.fromCache({
                blending : BlendingState.ALPHA_BLEND
            });
            drawCommand.uniformMap = this._uniformMap;
        }

        var sunPosition = context.uniformState.sunPositionWC;
        var sunPositionCV = context.uniformState.sunPositionColumbusView;

        var boundingVolume = this._boundingVolume;
        var boundingVolume2D = this._boundingVolume2D;

        Cartesian3.clone(sunPosition, boundingVolume.center);
        boundingVolume2D.center.x = sunPositionCV.z;
        boundingVolume2D.center.y = sunPositionCV.x;
        boundingVolume2D.center.z = sunPositionCV.y;

        boundingVolume.radius = CesiumMath.SOLAR_RADIUS + CesiumMath.SOLAR_RADIUS * this._glowLengthTS;
        boundingVolume2D.radius = boundingVolume.radius;

        if (mode === SceneMode.SCENE3D) {
            BoundingSphere.clone(boundingVolume, drawCommand.boundingVolume);
        } else if (mode === SceneMode.COLUMBUS_VIEW) {
            BoundingSphere.clone(boundingVolume2D, drawCommand.boundingVolume);
        }

        var position = SceneTransforms.computeActualWgs84Position(frameState, sunPosition, scratchCartesian4);

        var dist = Cartesian3.magnitude(Cartesian3.subtract(position, scene.camera.position, scratchCartesian4));
        var projMatrix = context.uniformState.projection;

        var positionEC = scratchPositionEC;
        positionEC.x = 0;
        positionEC.y = 0;
        positionEC.z = -dist;
        positionEC.w = 1;

        var positionCC = Matrix4.multiplyByVector(projMatrix, positionEC, scratchCartesian4);
        var positionWC = SceneTransforms.clipToDrawingBufferCoordinates(scene, positionCC, scratchPositionWC);

        positionEC.x = CesiumMath.SOLAR_RADIUS;
        var limbCC = Matrix4.multiplyByVector(projMatrix, positionEC, scratchCartesian4);
        var limbWC = SceneTransforms.clipToDrawingBufferCoordinates(scene, limbCC, scratchLimbWC);

        this._size = Math.ceil(Cartesian2.magnitude(Cartesian2.subtract(limbWC, positionWC, scratchCartesian4)));
        this._size = 2.0 * this._size * (1.0 + 2.0 * this._glowLengthTS);

        return this._commands;
    };

    /**
     * Returns true if this object was destroyed; otherwise, false.
     *

     * If this object was destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.
     *
     * @returns {Boolean} true if this object was destroyed; otherwise, false.
     *
     * @see Sun#destroy
     */
    Sun.prototype.isDestroyed = function() {
        return false;
    };

    /**
     * Destroys the WebGL resources held by this object.  Destroying an object allows for deterministic
     * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
     *

     * Once an object is destroyed, it should not be used; calling any function other than
     * isDestroyed will result in a {@link DeveloperError} exception.  Therefore,
     * assign the return value (undefined) to the object as done in the example.
     *
     * @returns {undefined}
     *
     * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
     *
     * @see Sun#isDestroyed
     *
     * @example
     * sun = sun && sun.destroy();
     */
    Sun.prototype.destroy = function() {
        var command = this._drawCommand;
        command.vertexArray = command.vertexArray && command.vertexArray.destroy();
        command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();

        this._texture = this._texture && this._texture.destroy();

        return destroyObject(this);
    };

    return Sun;
});
<|endoftext|>


<commit_before>define(["jquery", "ceci"], function($, Ceci) {
  "use strict";

  var broadcastBlock = document.createElement("broadcast");
  broadcastBlock.setAttribute("class","channel-visualisation broadcast-channels");

  var subscriptionBlock = document.createElement("listen");
  subscriptionBlock.setAttribute("class","channel-visualisation subscription-channels");

  var subscriptionMenuToggle = document.createElement("div");
  subscriptionMenuToggle.setAttribute("class", "channel-menu-toggle");
  subscriptionBlock.appendChild(subscriptionMenuToggle.cloneNode(true));

  var broadcastMenuToggle = document.createElement("div");
  broadcastMenuToggle.setAttribute("class", "channel-menu-toggle");
  broadcastBlock.appendChild(broadcastMenuToggle.cloneNode(true));

  var channelDot = document.createElement("div");
  channelDot.setAttribute("class", "color dot");

  var channelBlock = document.createElement("div");

  channelBlock.setAttribute("class", "channel");
  channelBlock.appendChild(channelDot.cloneNode(true));

  // channel visualisation animations
  var signalSpeed = 1;
  var bubbleDuration = 1;

  var setChannelIndicator = function(element, type, channel, listener) {
    // do we need to add the visualisation block?
    if(!element.querySelector(".broadcast-channels")) {
      element.appendChild(broadcastBlock.cloneNode(true));
      element.appendChild(subscriptionBlock.cloneNode(true));
    }

    // get the selector for the element whose color we need to change
    var sel = "." + type + "-channels",
        lsel = sel + " .channel" + (listener ? '.' + listener : ''),
        cblock;

    if(!element.querySelector(lsel)) {
      cblock = channelBlock.cloneNode(true);
      if(listener) {
        cblock.classList.add(listener);
      }
      element.querySelector(sel).appendChild(cblock);
    }

    // set relevant channel color, or remove if disabled
    var channelElement = cblock || element.querySelector(lsel);
    channelElement.setAttribute("color",channel);
    channelElement.setAttribute("title", listener ?  listener : "broadcast channel");
  };

  var CeciUI = function(element, def) {
    var elementAttributes = {},
        editableAttributes = [];

    var bindAttributeChanging = function(target, attrName, fallthrough) {
      // value tracking as "real" value
      var v = false;

      Object.defineProperty(target, attrName, {
        enumerable: false,
        configurable: true,
        get: function() {
          return v;
        },
        set: function(v) {
          target.setAttribute(attrName, v);
        }
      });

      // feedback and mutation observing based on HTML attribute
      var handler = function(mutations) {
        mutations.forEach(function(mutation) {
          v = target.getAttribute(attrName);
          if (fallthrough) {
            fallthrough.call(target, v);
          }
        });
      };

      var observer = new MutationObserver(handler);
      var config = { attributes: true, attributeFilter: [attrName] };

      observer.observe(target, config);
    };

    if (def.editable) {
      Object.keys(def.editable).forEach(function (key) {
        var props = def.editable[key];
        bindAttributeChanging(element, key, props.postset);
        editableAttributes.push(key);
        var eak = {};
        Object.keys(props).forEach(function(pkey) {
          if (pkey === "postset") return;
          eak[pkey] = props[pkey];
        });
        elementAttributes[key] = eak;
      });
    }

    element.addDataBubble = function(element, direction, data) {
      var timeout = (direction === "out" ? 0 : signalSpeed * 1000);
      setTimeout(function() {
        var bubble = document.createElement("div");
        $(bubble).text(data).addClass("bubblepopup").addClass("bubblepop");
        $(element).append(bubble);
        setTimeout(function() {
          $(bubble).remove();
        }, bubbleDuration * 1000);
      }, timeout);
    };

    element.addIndicator = function(element, direction) {
      var indicator = document.createElement("div");
      $(element).append(indicator);
      $(indicator).addClass("indicator indicator-" + direction);
      var signalSpeedCSS = signalSpeed + "s";
      $(indicator).css({
        "-webkit-animation-duration": signalSpeedCSS,
        "-moz-animation-duration": signalSpeedCSS
      });
      if(direction == "out") {
        var colors = $(element).find(".color"),
            removePulse = function() {
              $(colors).removeClass("pulse");
            };
        colors.addClass("pulse").bind("webkitAnimationEnd animationend", removePulse);
      }
      var removeIndicator = function() {
        $(indicator).remove();
      };
      setTimeout(removeIndicator, signalSpeed * 1000);
    };

    element.getEditableAttributes = function() {
      return editableAttributes;
    };

    element.getAttributeDefinition = function(attrName) {
      return elementAttributes[attrName];
    };

    element.onBroadcastChannelChanged = function(channel) {
      setChannelIndicator(element, 'broadcast', channel);
    };

    element.onSubscriptionChannelChanged = function(channel, listener) {
      setChannelIndicator(element, 'subscription', channel, listener);
    };

    element.onOutputGenerated = function(channel, output) {
      var bc = element.querySelector(".broadcast-channels .channel[color="+channel+"]");
      element.addIndicator(bc, "out");
      element.addDataBubble(bc, "out", output);
    };

    element.onInputReceived = function(channel, input) {
      var bc = element.querySelector(".subscription-channels .channel[color="+channel+"]");
      element.addIndicator(bc, "in");
      element.addDataBubble(bc, "in", input);
    };

    element.log = function(message, channel, severity) {
      if (severity === undefined) severity = 0;
      Ceci.log(element, message, channel, severity);
    };

    element.lookAtMe = function() {
      Ceci.elementWantsAttention(this);
    };
  };

  // register ourselves with Ceci
  Ceci.reserveKeyword("editable");
  Ceci.registerCeciPlugin("constructor", CeciUI);

  // return this plugin, for good measure
  return CeciUI;
});
<commit_msg>if an element has two listeners on the same channel, both receive the animation on listen now<commit_after>define(["jquery", "ceci"], function($, Ceci) {
  "use strict";

  var broadcastBlock = document.createElement("broadcast");
  broadcastBlock.setAttribute("class","channel-visualisation broadcast-channels");

  var subscriptionBlock = document.createElement("listen");
  subscriptionBlock.setAttribute("class","channel-visualisation subscription-channels");

  var subscriptionMenuToggle = document.createElement("div");
  subscriptionMenuToggle.setAttribute("class", "channel-menu-toggle");
  subscriptionBlock.appendChild(subscriptionMenuToggle.cloneNode(true));

  var broadcastMenuToggle = document.createElement("div");
  broadcastMenuToggle.setAttribute("class", "channel-menu-toggle");
  broadcastBlock.appendChild(broadcastMenuToggle.cloneNode(true));

  var channelDot = document.createElement("div");
  channelDot.setAttribute("class", "color dot");

  var channelBlock = document.createElement("div");

  channelBlock.setAttribute("class", "channel");
  channelBlock.appendChild(channelDot.cloneNode(true));

  // channel visualisation animations
  var signalSpeed = 1;
  var bubbleDuration = 1;

  var setChannelIndicator = function(element, type, channel, listener) {
    // do we need to add the visualisation block?
    if(!element.querySelector(".broadcast-channels")) {
      element.appendChild(broadcastBlock.cloneNode(true));
      element.appendChild(subscriptionBlock.cloneNode(true));
    }

    // get the selector for the element whose color we need to change
    var sel = "." + type + "-channels",
        lsel = sel + " .channel" + (listener ? '.' + listener : ''),
        cblock;

    if(!element.querySelector(lsel)) {
      cblock = channelBlock.cloneNode(true);
      if(listener) {
        cblock.classList.add(listener);
      }
      element.querySelector(sel).appendChild(cblock);
    }

    // set relevant channel color, or remove if disabled
    var channelElement = cblock || element.querySelector(lsel);
    channelElement.setAttribute("color",channel);
    channelElement.setAttribute("title", listener ?  listener : "broadcast channel");
  };

  var CeciUI = function(element, def) {
    var elementAttributes = {},
        editableAttributes = [];

    var bindAttributeChanging = function(target, attrName, fallthrough) {
      // value tracking as "real" value
      var v = false;

      Object.defineProperty(target, attrName, {
        enumerable: false,
        configurable: true,
        get: function() {
          return v;
        },
        set: function(v) {
          target.setAttribute(attrName, v);
        }
      });

      // feedback and mutation observing based on HTML attribute
      var handler = function(mutations) {
        mutations.forEach(function(mutation) {
          v = target.getAttribute(attrName);
          if (fallthrough) {
            fallthrough.call(target, v);
          }
        });
      };

      var observer = new MutationObserver(handler);
      var config = { attributes: true, attributeFilter: [attrName] };

      observer.observe(target, config);
    };

    if (def.editable) {
      Object.keys(def.editable).forEach(function (key) {
        var props = def.editable[key];
        bindAttributeChanging(element, key, props.postset);
        editableAttributes.push(key);
        var eak = {};
        Object.keys(props).forEach(function(pkey) {
          if (pkey === "postset") return;
          eak[pkey] = props[pkey];
        });
        elementAttributes[key] = eak;
      });
    }

    element.addDataBubble = function(element, direction, data) {
      var timeout = (direction === "out" ? 0 : signalSpeed * 1000);
      setTimeout(function() {
        var bubble = document.createElement("div");
        $(bubble).text(data).addClass("bubblepopup").addClass("bubblepop");
        $(element).append(bubble);
        setTimeout(function() {
          $(bubble).remove();
        }, bubbleDuration * 1000);
      }, timeout);
    };

    element.addIndicator = function(element, direction) {
      var indicator = document.createElement("div");
      $(element).append(indicator);
      $(indicator).addClass("indicator indicator-" + direction);
      var signalSpeedCSS = signalSpeed + "s";
      $(indicator).css({
        "-webkit-animation-duration": signalSpeedCSS,
        "-moz-animation-duration": signalSpeedCSS
      });
      if(direction == "out") {
        var colors = $(element).find(".color"),
            removePulse = function() {
              $(colors).removeClass("pulse");
            };
        colors.addClass("pulse").bind("webkitAnimationEnd animationend", removePulse);
      }
      var removeIndicator = function() {
        $(indicator).remove();
      };
      setTimeout(removeIndicator, signalSpeed * 1000);
    };

    element.getEditableAttributes = function() {
      return editableAttributes;
    };

    element.getAttributeDefinition = function(attrName) {
      return elementAttributes[attrName];
    };

    element.onBroadcastChannelChanged = function(channel) {
      setChannelIndicator(element, 'broadcast', channel);
    };

    element.onSubscriptionChannelChanged = function(channel, listener) {
      setChannelIndicator(element, 'subscription', channel, listener);
    };

    element.onOutputGenerated = function(channel, output) {
      var bc = element.querySelector(".broadcast-channels .channel[color="+channel+"]");
      element.addIndicator(bc, "out");
      element.addDataBubble(bc, "out", output);
    };

    element.onInputReceived = function(channel, input) {
      var bc = element.querySelectorAll(".subscription-channels .channel[color="+channel+"]");
      for(var i = 0; i < bc.length; ++i) {
        element.addIndicator(bc[i], "in");
        element.addDataBubble(bc[i], "in", input);
      }
    };

    element.log = function(message, channel, severity) {
      if (severity === undefined) severity = 0;
      Ceci.log(element, message, channel, severity);
    };

    element.lookAtMe = function() {
      Ceci.elementWantsAttention(this);
    };
  };

  // register ourselves with Ceci
  Ceci.reserveKeyword("editable");
  Ceci.registerCeciPlugin("constructor", CeciUI);

  // return this plugin, for good measure
  return CeciUI;
});
<|endoftext|>


<commit_before>const Notification = require('./Notification');

async function Verification( request, reply ) {
  console.log(request);
  // const notificationResult = await Notification({
  //   status: 'Error',
  //   description: `There was an error proccesing`,
  //   room: request.query.hipchat,
  //   url: request.query.site,
  // });
  return reply({});
}

module.exports = Verification;
<commit_msg>Send notifications from the verification<commit_after>const Notification = require('./Notification');
const fetch = require('node-fetch'); // polyfill

const SCORE = {
  GOOD: 75,
  AVARAGE: 45,
}

async function sendNotification( total = 0, url, hipchat, report ) {
  // Set error as default.
  let notificationOpts = {
    room: hipchat,
    url: url,
    description: `The score for your <a href="${url}">site</a> was <a href="${report}"><b>${total.toFixed(2)} / 100</b></a>. <a href="${report}">Full report</a>.`,
  }

  if ( total >= SCORE.GOOD ) {
    notificationOpts.status = 'Good';
  } else if ( total >= SCORE.AVARAGE ) {
    notificationOpts.status = 'Avarage';
  } else {
    notificationOpts.status = 'Fail';
  }
  return await Notification(notificationOpts);
}

async function Verification( request, reply ) {
  const { id } = request.query;
  const BASE = `https://www.webpagetest.org/jsonResult.php?test=${id}`;
  const testRequest = await fetch(BASE);
  const json = await testRequest.json();
  const data = 'data' in json ? json.data : {};
  let { lighthouse, html_result_url } = data;
  lighthouse = lighthouse || {};
  const { url } = lighthouse;
  const score = lighthouse.aggregations.reduce( (accumulator, item) => {
    return accumulator + item.total;
  }, 0);
  const total = score * 100;
  const result = sendNotification(total, url, request.params.hipchat, html_result_url);
  return reply(result);
}

module.exports = Verification;
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global $, jQuery*/

(function(){
    "use strict";

    $(".datepicker").datepicker({
        format: 'yyyy-mm-dd',

    });

}());
<commit_msg>fix: removed obsolete file<commit_after><|endoftext|>


<commit_before>var compose = require('ksf/utils/compose');

module.exports = compose(function(tag, namespace) {
	var node;
	if (namespace) {
		node = this.domNode = document.createElementNS(namespace, tag);
	} else {
		node = this.domNode = document.createElement(tag || 'div');
	}
	node.style.position = 'absolute';
	node.style.boxSizing = 'border-box';
	node.style.display = 'block'; // est-ce nécessaire de le forcer au démarrage ?
	this._visible = true;
	node.style['-webkit-transform'] = 'translateZ(0px)';
}, {
	left: function(left) {
		if (arguments.length) {
			this._left = left;
			this.domNode.style.left = left+'px';
			return this;
		} else {
			return this._left;
		}
	},
	top: function(top) {
		if (arguments.length) {
			this._top = top;
			this.domNode.style.top = top+'px';
			return this;
		} else {
			return this._top;
		}
	},
	zIndex: function(zIndex) {
		if (arguments.length) {
			this._zIndex = zIndex;
			this.domNode.style.zIndex = zIndex;
			return this;
		} else {
			return this._zIndex;
		}
	},
	width: function(width) {
		if (arguments.length) {
			this._width = width;
			this.domNode.style.width = width+'px';
			return this;
		} else {
			return this._width;
		}
	},
	height: function(height) {
		if (arguments.length) {
			this._height = height;
			this.domNode.style.height = height+'px';
			return this;
		} else {
			return this._height;
		}
	},
	depth: function() {
		return 1;
	},
	parentNode: function(parentNode) {
		if (arguments.length) {
			if (parentNode) {
				parentNode.appendChild(this.domNode);
			} else {
				this._parentNode && this._parentNode.removeChild(this.domNode);
			}
			this._parentNode = parentNode;
			return this;
		} else {
			return this._parentNode;
		}
	},
	visible: function(visible) {
		if (arguments.length) {
			this._visible = visible;
			this.domNode.style.display = (visible ? 'block' : 'none');
			return this;
		} else {
			return this._visible;
		}
	},
	attr: function(attr, value) {
		this.domNode.setAttribute(attr, value);
	},
	attrs: function(attrs) {
		Object.keys(attrs).forEach(function(attr) {
			this.attr(attr, attrs[attr]);
		}, this);
		return this;
	},
	prop: function(prop, value) {
		if (arguments.length === 2) {
			this.domNode[prop] = value;
			return this;
		} else {
			return this.domNode[prop];
		}
	},
	props: function(props) {
		Object.keys(props).forEach(function(prop) {
			this.prop(prop, props[prop]);
		}, this);
		return this;
	},
	styleProp: function(prop, value) {
		this.domNode.style[prop] = value;
		return this;
	},
	style: function(style) {
		Object.keys(style).forEach(function(prop) {
			this.styleProp(prop, style[prop]);
		}, this);
		return this;
	},
	on: function(type, cb) {
		this.domNode.addEventListener(type, cb);
	},
	off: function(type, cb) {
		this.domNode.removeEventListener(type, cb);
	},
});
<commit_msg>Element update : global style<commit_after>var compose = require('ksf/utils/compose');
var JSS = require('ksf/dom/style/JSS');

var baseStyle = new JSS({
	position: 'absolute',
	boxSizing: 'border-box',
	// est-ce nécessaire de le forcer au démarrage ?
	display: 'block',
	// nécessaire pour les cas où cet élément est ajouté dans un dom-node avec pointer-events: none (transparent)
	pointerEvents: 'auto',
});

module.exports = compose(function(tag, namespace) {
	var node;
	if (namespace) {
		node = this.domNode = document.createElementNS(namespace, tag);
	} else {
		node = this.domNode = document.createElement(tag || 'div');
	}
	this._visible = true;
	baseStyle.apply(this.domNode);
}, {
	left: function(left) {
		if (arguments.length) {
			this._left = left;
			this.domNode.style.left = left+'px';
			return this;
		} else {
			return this._left;
		}
	},
	top: function(top) {
		if (arguments.length) {
			this._top = top;
			this.domNode.style.top = top+'px';
			return this;
		} else {
			return this._top;
		}
	},
	zIndex: function(zIndex) {
		if (arguments.length) {
			this._zIndex = zIndex;
			this.domNode.style.zIndex = zIndex;
			return this;
		} else {
			return this._zIndex;
		}
	},
	width: function(width) {
		if (arguments.length) {
			this._width = width;
			this.domNode.style.width = width+'px';
			return this;
		} else {
			return this._width;
		}
	},
	height: function(height) {
		if (arguments.length) {
			this._height = height;
			this.domNode.style.height = height+'px';
			return this;
		} else {
			return this._height;
		}
	},
	depth: function() {
		return 1;
	},
	parentNode: function(parentNode) {
		if (arguments.length) {
			if (parentNode) {
				parentNode.appendChild(this.domNode);
			} else {
				this._parentNode && this._parentNode.removeChild(this.domNode);
			}
			this._parentNode = parentNode;
			return this;
		} else {
			return this._parentNode;
		}
	},
	visible: function(visible) {
		if (arguments.length) {
			this._visible = visible;
			this.domNode.style.display = (visible ? '' : 'none');
			return this;
		} else {
			return this._visible;
		}
	},
	attr: function(attr, value) {
		this.domNode.setAttribute(attr, value);
		return this;
	},
	attrs: function(attrs) {
		Object.keys(attrs).forEach(function(attr) {
			this.attr(attr, attrs[attr]);
		}, this);
		return this;
	},
	prop: function(prop, value) {
		if (arguments.length === 2) {
			this.domNode[prop] = value;
			return this;
		} else {
			return this.domNode[prop];
		}
	},
	props: function(props) {
		Object.keys(props).forEach(function(prop) {
			this.prop(prop, props[prop]);
		}, this);
		return this;
	},
	styleProp: function(prop, value) {
		this.domNode.style[prop] = value;
		return this;
	},
	style: function(style) {
		Object.keys(style).forEach(function(prop) {
			this.styleProp(prop, style[prop]);
		}, this);
		return this;
	},
	on: function(type, cb) {
		this.domNode.addEventListener(type, cb);
	},
	off: function(type, cb) {
		this.domNode.removeEventListener(type, cb);
	},
});
<|endoftext|>


<commit_before>import passport from 'passport'
import { Strategy as LocalStrategy } from 'passport-local'
import { BasicStrategy } from 'passport-http'
import { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password'
import { Strategy as BearerStrategy } from 'passport-http-bearer'
import { OAuthUser, OAuthClient } from '../models'
import OAuthToken, { verifyToken } from '../models/oauth_token'

/**
 * LocalStrategy
 *
 * This strategy is used to authenticate users based on a username and password.
 * Anytime a request is made to authorize an application, we must ensure that
 * a user is logged in before asking them to approve the request.
 */
const local = new LocalStrategy(async (usernameOrEmail, password, done) => {
  try {
    const user = await OAuthUser.findByUsernameOrEmail(usernameOrEmail)
    if (!user) return done(null, false)
    const isAuthenticated = await user.authenticate(password)
    if (!isAuthenticated) return done(null, false)
    done(null, user)
  } catch (err) {
    done(err)
  }
})

/**
 * BasicStrategy & ClientPasswordStrategy
 *
 * These strategies are used to authenticate registered OAuth clients.  They are
 * employed to protect the `token` endpoint, which consumers use to obtain
 * access tokens.  The OAuth 2.0 specification suggests that clients use the
 * HTTP Basic scheme to authenticate.  Use of the client password strategy
 * allows clients to send the same credentials in the request body (as opposed
 * to the `Authorization` header).  While this approach is not recommended by
 * the specification, in practice it is quite common.
 */
const basic = new BasicStrategy(async (username, password, done) => {
  try {
    const client = await OAuthClient.findByClientId(username)
    if (!client) return done(null, false)
    if (client.clientSecret !== password) return done(null, false)
    done(null, client)
  } catch (err) {
    done(err)
  }
})

/**
 * Client Password strategy
 *
 * The OAuth 2.0 client password authentication strategy authenticates clients
 * using a client ID and client secret. The strategy requires a verify callback,
 * which accepts those credentials and calls done providing a client.
 */

const oauth2ClientPassword = new ClientPasswordStrategy(async (clientId, clientSecret, done) => {
  try {
    const client = await OAuthClient.findByClientId(clientId)
    if (!client) return done(null, false)
    if (client.clientSecret !== clientSecret) return done(null, false)
    return done(null, client)
  } catch (err) {
    done(err)
  }
})

/**
 * BearerStrategy
 *
 * This strategy is used to authenticate either users or clients based on an access token
 * (aka a bearer token).  If a user, they must have previously authorized a client
 * application, which is issued an access token to make requests on behalf of
 * the authorizing user.
 *
 * To keep this example simple, restricted scopes are not implemented, and this is just for
 * illustrative purposes
 */
const bearer = new BearerStrategy(async (accessToken, done) => {
  try {
    verifyToken(accessToken)

    const token = await OAuthToken.findToken(accessToken)
    if (!token) throw new Error('Invalid token')

    const { user: userId, clientId } = token.payload

    const user = (userId)
      ? await OAuthUser.findById(userId)
      : await OAuthClient.findByClientId(clientId)

    done(null, user, token.payload)
  } catch (err) {
    done(err)
  }
})

// Register serialialization and deserialization functions.
//
// When a client redirects a user to user authorization endpoint, an
// authorization transaction is initiated.  To complete the transaction, the
// user must authenticate and approve the authorization request.  Because this
// may involve multiple HTTPS request/response exchanges, the transaction is
// stored in the session.
//
// An application must supply serialization functions, which determine how the
// client object is serialized into the session.  Typically this will be a
// simple matter of serializing the client's ID, and deserializing by finding
// the client by ID from the database.

const serializeUser = (user, done) => done(null, user)
const deserializeUser = (user, done) => done(null, user)

export default function setupPassport () {
  passport.use(local)
  passport.use(basic)
  passport.use(oauth2ClientPassword)
  passport.use(bearer)
  passport.serializeUser(serializeUser)
  passport.deserializeUser(deserializeUser)
}
<commit_msg>refactor: passport<commit_after>import passport from 'passport'
import { Strategy as LocalStrategy } from 'passport-local'
import { BasicStrategy } from 'passport-http'
import { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password'
import { Strategy as BearerStrategy } from 'passport-http-bearer'
import { OAuthUser, OAuthClient } from '../models'
import OAuthToken, { verifyToken } from '../models/oauth_token'

/**
 * LocalStrategy
 *
 * This strategy is used to authenticate users based on a username and password.
 * Anytime a request is made to authorize an application, we must ensure that
 * a user is logged in before asking them to approve the request.
 */
const local = new LocalStrategy(async (usernameOrEmail, password, done) => {
  try {
    const user = await OAuthUser.findByUsernameOrEmail(usernameOrEmail)
    if (!user) return done(null, false)
    const isAuthenticated = await user.authenticate(password)
    if (!isAuthenticated) return done(null, false)
    done(null, user)
  } catch (err) {
    done(err)
  }
})

/**
 * BasicStrategy & ClientPasswordStrategy
 *
 * These strategies are used to authenticate registered OAuth clients.  They are
 * employed to protect the `token` endpoint, which consumers use to obtain
 * access tokens.  The OAuth 2.0 specification suggests that clients use the
 * HTTP Basic scheme to authenticate.  Use of the client password strategy
 * allows clients to send the same credentials in the request body (as opposed
 * to the `Authorization` header).  While this approach is not recommended by
 * the specification, in practice it is quite common.
 */
const basic = new BasicStrategy(async (username, password, done) => {
  try {
    const client = await OAuthClient.findByClientId(username)
    if (!client) return done(null, false)
    if (client.clientSecret !== password) return done(null, false)
    done(null, client)
  } catch (err) {
    done(err)
  }
})

/**
 * Client Password strategy
 *
 * The OAuth 2.0 client password authentication strategy authenticates clients
 * using a client ID and client secret. The strategy requires a verify callback,
 * which accepts those credentials and calls done providing a client.
 */

const oauth2ClientPassword = new ClientPasswordStrategy(async (clientId, clientSecret, done) => {
  try {
    const client = await OAuthClient.findByClientId(clientId)
    if (!client) return done(null, false)
    if (client.clientSecret !== clientSecret) return done(null, false)
    return done(null, client)
  } catch (err) {
    done(err)
  }
})

/**
 * BearerStrategy
 *
 * This strategy is used to authenticate either users or clients based on an access token
 * (aka a bearer token).  If a user, they must have previously authorized a client
 * application, which is issued an access token to make requests on behalf of
 * the authorizing user.
 *
 * To keep this example simple, restricted scopes are not implemented, and this is just for
 * illustrative purposes
 */
const bearer = new BearerStrategy(async (accessToken, done) => {
  try {
    verifyToken(accessToken)

    const token = await OAuthToken.findToken(accessToken)
    if (!token) throw new Error('Invalid token')

    const { user: userId, clientId, scope } = token.payload

    const user = (userId)
      ? await OAuthUser.findById(userId)
      : await OAuthClient.findByClientId(clientId)

    done(null, user, { scope })
  } catch (err) {
    done(err)
  }
})

// Register serialialization and deserialization functions.
//
// When a client redirects a user to user authorization endpoint, an
// authorization transaction is initiated.  To complete the transaction, the
// user must authenticate and approve the authorization request.  Because this
// may involve multiple HTTPS request/response exchanges, the transaction is
// stored in the session.
//
// An application must supply serialization functions, which determine how the
// client object is serialized into the session.  Typically this will be a
// simple matter of serializing the client's ID, and deserializing by finding
// the client by ID from the database.

const serializeUser = (user, done) => done(null, user)
const deserializeUser = (user, done) => done(null, user)

export default function setupPassport () {
  passport.use(local)
  passport.use(basic)
  passport.use(oauth2ClientPassword)
  passport.use(bearer)
  passport.serializeUser(serializeUser)
  passport.deserializeUser(deserializeUser)
}
<|endoftext|>


<commit_before>/*SOURCE: code from https://github.com/knoldus/Node.js_UserLogin_Template*/
var logger = require("../logger/logger");
var userHelper = require('../services/userHelper');

var wrap = require('co-express');
var co = require('co');

// local authentication
// For more details go to https://github.com/jaredhanson/passport-local
var LocalStrategy = require('passport-local').Strategy;
var BasicStrategy = require('passport-http').BasicStrategy;

// Facebook authentication
// For more details go to https://github.com/jaredhanson/passport-facebook
var FacebookStrategy = require('passport-facebook').Strategy;
var FACEBOOK_APP_ID = "<Insert Your Key Here>"
var FACEBOOK_APP_SECRET = "<Insert Your Secret Key Here>";

// Twitter authentication
// For more details go to https://github.com/jaredhanson/passport-twitter
var TwitterStrategy = require('passport-twitter').Strategy;
var TWITTER_CONSUMER_KEY = "<Insert Your Key Here>";
var TWITTER_CONSUMER_SECRET = "<Insert Your Secret Key Here>";

// Google authentication
// For more details go to https://github.com/jaredhanson/passport-google-oauth
var GOOGLE_CONSUMER_KEY = "<Insert Your Key Here>";
var GOOGLE_CONSUMER_SECRET = "<Insert Your Secret Key Here>";
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy

//TODO: passport-github

var User = require('../models/user');

module.exports = function(app, passport) {

    // Maintaining persistent login sessions
    // serialized  authenticated user to the session
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });

    // deserialized when subsequent requests are made
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

    passport.use('local', new LocalStrategy({
            usernameField: 'username',
            passReqToCallback: true
        },
        function(req, username, password, done) {
            process.nextTick(function() {
                User.findOne({ $or: [{ email: username }, { username: username }] }, function(err, user) {
                    if (err) {
                        logger.err(err);
                        req = userHelper.processUser(req);
                        return done(err, req.flash('error', '' + err));
                    }
                    if (!user) {
                        logger.warn('Incorrect username.');
                        req = userHelper.processUser(req);
                        return done(null, false, req.flash('error', 'User does not exist.'));
                    }

                    if (!user.verifyPassword(password)) {
                        logger.warn('Incorrect password.');
                        req = userHelper.processUser(req);
                        return done(null, false, req.flash('error', 'Enter correct password'));
                    }

                    user.lastLoginDate = new Date();
                    user.save();

                    req = userHelper.processUser(req);
                    return done(null, user, req.flash('success', 'user logged in.'));

                });
            });

        }));

    passport.use('basic', new BasicStrategy( //TODO: JMC fix
        function(username, password, done) {
            User.findOne({ $or: [{ email: username }, { username: username }] }, function(err, user) {
                if (err) {
                    user.isLoggedIn = false;
                    return done(err, req.flash('error', '' + err));
                }
                if (!user) {
                    user.isLoggedIn = false;
                    logger.warn('User does not exist');
                    return done(null, false, req.flash('error', 'User does not exist.'));
                }

                if (!user.verifyPassword(password)) {
                    logger.warn('Incorrect password.');
                    user.isLoggedIn = false;
                    return done(null, false, req.flash('error', 'Enter correct password'));
                }

                user.lastLoginDate = new Date();
                user.save();

                req = userHelper.processUser(req);
                return done(null, user, req.flash('success', 'user logged in.'));
            });
        }
    ));

    passport.use('signup', new LocalStrategy({
            usernameField: 'username',
            passReqToCallback: true
        },
        function(req, username, password, done) {

            process.nextTick(function() {

                if (!req.user) {
                    User.findOne({ $or: [{ email: username }, { username: username }] }, wrap(function*(err, user) {
                        if (err) {
                            return done(err, req.flash('error', '' + err));
                        }
                        if (user) {
                            return done(null, false, req.flash('error', 'User already exists', null));
                        } else {
                            var newUser = yield userHelper.createNewUser(username, password, req.body);
                            newUser.save(function(err) {
                                if (err)
                                    throw err; //TODO JMC Fix
                                req.user = newUser;
                                req = userHelper.processUser(req);
                                logger.warn("created new user");

                                if (req.user.isStudent) {
                                    req.flash('success', 'You are a student, we have given you R1000 store credit');
                                }

                                return done(null, newUser, req.flash('success', 'created new user'));
                            });
                        }

                    }));
                } else {
                    co(function*() {
                        var newUser = yield userHelper.createNewUser(username, password, req.body);
                        newUser.save(function(err) {
                            if (err)
                                throw err;

                            req.user = newUser;
                            req = userHelper.processUser(req);
                            logger.warn("created new user");

                            if (req.user.isStudent) {
                                req.flash('success', 'You are a student, we have given you R1000 store credit');
                            }

                            return done(null, newUser, req.flash('success', 'created new user'));
                        });
                    })
                }

            });

        }));

    // Use the FacebookStrategy within Passport.
    // Strategies in Passport require a `verify` function, which accept
    // credentials (in this case, an accessToken, refreshToken, and Facebook
    // profile), and invoke a callback with a user object.
    passport.use(new FacebookStrategy({
            clientID: FACEBOOK_APP_ID,
            clientSecret: FACEBOOK_APP_SECRET,
            callbackURL: "http://localhost:8080/auth/facebook/callback"
        },
        function(req, accessToken, refreshToken, profile, done) {
            // asynchronous verification, for effect...

            process.nextTick(function() {
                if (!req.user) {
                    User.findOne({ 'user.email': profile.emails[0].value }, function(err, user) {
                        if (err) {
                            return done(err);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            var newUser = new User();
                            newUser.user.username = profile.displayName;
                            newUser.user.email = profile.emails[0].value;
                            newUser.user.name = ''
                            newUser.user.address = ''

                            newUser.save(function(err) {
                                if (err)
                                    throw err;
                                return done(null, newUser);
                            });
                        }

                    });
                } else {
                    var user = req.user;
                    user.user.username = profile.displayName;
                    user.user.email = profile.emails[0].value;
                    user.user.name = ''
                    user.user.address = ''

                    user.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, user);
                    });
                }
            });
        }
    ));

    // Use the TwitterStrategy within Passport.
    // Strategies in passport require a `verify` function, which accept
    // credentials (in this case, a token, tokenSecret, and Twitter profile), and
    // invoke a callback with a user object.
    passport.use(new TwitterStrategy({
            consumerKey: TWITTER_CONSUMER_KEY,
            consumerSecret: TWITTER_CONSUMER_SECRET,
            callbackURL: "http://192.168.1.101:8080/auth/twitter/callback"
        },
        function(req, token, tokenSecret, profile, done) {
            // asynchronous verification, for effect...
            process.nextTick(function() {

                if (!req.user) {
                    User.findOne({ 'user.username': profile.displayName }, function(err, user) {
                        if (err) {
                            return done(err);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            var newUser = new User();
                            newUser.user.username = profile.displayName;
                            newUser.user.name = ''
                            newUser.user.address = ''

                            newUser.save(function(err) {
                                if (err)
                                    throw err;
                                return done(null, newUser);
                            });
                        }

                    });
                } else {
                    var user = req.user;
                    user.user.username = profile.displayName;
                    user.user.name = ''
                    user.user.address = ''

                    user.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, user);
                    });
                }
            });
        }
    ));

    // Use the GoogleStrategy within Passport.
    // Strategies in Passport require a `verify` function, which accept
    // credentials (in this case, an accessToken, refreshToken, and Google
    // profile), and invoke a callback with a user object.
    passport.use(new GoogleStrategy({
            clientID: GOOGLE_CONSUMER_KEY,
            clientSecret: GOOGLE_CONSUMER_SECRET,
            callbackURL: "http://localhost:8080/auth/google/callback"
        },
        function(req, accessToken, refreshToken, profile, done) {
            // asynchronous verification, for effect...
            process.nextTick(function() {

                if (!req.user) {
                    User.findOne({ 'user.email': profile.emails[0].value }, function(err, user) {
                        if (err) {
                            return done(err);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            var newUser = new User();
                            newUser.user.username = profile.displayName;
                            newUser.user.email = profile.emails[0].value;
                            newUser.user.name = ''
                            newUser.user.address = ''

                            newUser.save(function(err) {
                                if (err)
                                    throw err;
                                return done(null, newUser);
                            });
                        }

                    });
                } else {
                    var user = req.user;
                    user.user.username = profile.displayName;
                    user.user.email = profile.emails[0].value;
                    user.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, user);
                    });
                }
            });

        }

    ));

};
<commit_msg>student<commit_after>/*SOURCE: code from https://github.com/knoldus/Node.js_UserLogin_Template*/
var logger = require("../logger/logger");
var mongoose = require('../config/db.js').mongoose;
var userHelper = require('../services/userHelper');
var schoolDomain = mongoose.model('SchoolDomain', require('../models/schoolDomain'));

var wrap = require('co-express');
var co = require('co');

// local authentication
// For more details go to https://github.com/jaredhanson/passport-local
var LocalStrategy = require('passport-local').Strategy;
var BasicStrategy = require('passport-http').BasicStrategy;

// Facebook authentication
// For more details go to https://github.com/jaredhanson/passport-facebook
var FacebookStrategy = require('passport-facebook').Strategy;
var FACEBOOK_APP_ID = "<Insert Your Key Here>"
var FACEBOOK_APP_SECRET = "<Insert Your Secret Key Here>";

// Twitter authentication
// For more details go to https://github.com/jaredhanson/passport-twitter
var TwitterStrategy = require('passport-twitter').Strategy;
var TWITTER_CONSUMER_KEY = "<Insert Your Key Here>";
var TWITTER_CONSUMER_SECRET = "<Insert Your Secret Key Here>";

// Google authentication
// For more details go to https://github.com/jaredhanson/passport-google-oauth
var GOOGLE_CONSUMER_KEY = "<Insert Your Key Here>";
var GOOGLE_CONSUMER_SECRET = "<Insert Your Secret Key Here>";
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy

//TODO: passport-github

var User = require('../models/user');

module.exports = function(app, passport) {

    // Maintaining persistent login sessions
    // serialized  authenticated user to the session
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });

    // deserialized when subsequent requests are made
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

    passport.use('local', new LocalStrategy({
            usernameField: 'username',
            passReqToCallback: true
        },
        function(req, username, password, done) {
            process.nextTick(function() {
                User.findOne({ $or: [{ email: username }, { username: username }] }, function(err, user) {
                    if (err) {
                        logger.err(err);
                        req = userHelper.processUser(req);
                        return done(err, req.flash('error', '' + err));
                    }
                    if (!user) {
                        logger.warn('Incorrect username.');
                        req = userHelper.processUser(req);
                        return done(null, false, req.flash('error', 'User does not exist.'));
                    }

                    if (!user.verifyPassword(password)) {
                        logger.warn('Incorrect password.');
                        req = userHelper.processUser(req);
                        return done(null, false, req.flash('error', 'Enter correct password'));
                    }

                    user.lastLoginDate = new Date();
                    user.save();

                    req = userHelper.processUser(req);
                    return done(null, user, req.flash('success', 'user logged in.'));

                });
            });

        }));

    passport.use('basic', new BasicStrategy( //TODO: JMC fix
        function(username, password, done) {
            User.findOne({ $or: [{ email: username }, { username: username }] }, function(err, user) {
                if (err) {
                    user.isLoggedIn = false;
                    return done(err, req.flash('error', '' + err));
                }
                if (!user) {
                    user.isLoggedIn = false;
                    logger.warn('User does not exist');
                    return done(null, false, req.flash('error', 'User does not exist.'));
                }

                if (!user.verifyPassword(password)) {
                    logger.warn('Incorrect password.');
                    user.isLoggedIn = false;
                    return done(null, false, req.flash('error', 'Enter correct password'));
                }

                user.lastLoginDate = new Date();
                user.save();

                req = userHelper.processUser(req);
                return done(null, user, req.flash('success', 'user logged in.'));
            });
        }
    ));

    passport.use('signup', new LocalStrategy({
            usernameField: 'username',
            passReqToCallback: true
        },
        function(req, username, password, done) {

            process.nextTick(function() {

                if (!req.user) {
                    User.findOne({ $or: [{ email: username }, { username: username }] }, wrap(function*(err, user) {
                        if (err) {
                            return done(err, req.flash('error', '' + err));
                        }
                        if (user) {
                            return done(null, false, req.flash('error', 'User already exists', null));
                        } else {
                            var newUser = yield userHelper.createNewUser(username, password, req.body);
                            newUser.save(function(err) {
                                if (err)
                                    throw err; //TODO JMC Fix

                                schoolDomain.findOne({}, function(err, domainObj) {
                                    var isStudent = domainObj.isStudentEmail(iUser.email);

                                    if (isStudent) {
                                        newUser.money = 1000;
                                        newUser.isStudent = true;
                                    } else {
                                        newUser.money = 0;
                                        newUser.isStudent = false;
                                    }

                                    if (isStudent) {
                                        req.flash('success', 'Because You are a student, we have given you R1000 store credit');
                                    }

                                });

                                req.user = newUser;
                                req = userHelper.processUser(req);
                                logger.warn("created new user");

                                return done(null, newUser, req.flash('success', 'created new user'));
                            });
                        }

                    }));
                } else {
                    co(function*() {
                        var newUser = yield userHelper.createNewUser(username, password, req.body);
                        newUser.save(function(err) {
                            if (err)
                                throw err;

                            schoolDomain.findOne({}, function(err, domainObj) {
                                var isStudent = domainObj.isStudentEmail(iUser.email);

                                if (isStudent) {
                                    newUser.money = 1000;
                                    newUser.isStudent = true;
                                } else {
                                    newUser.money = 0;
                                    newUser.isStudent = false;
                                }

                                if (isStudent) {
                                    req.flash('success', 'Because You are a student, we have given you R1000 store credit');
                                }

                            });

                            req.user = newUser;
                            req = userHelper.processUser(req);
                            logger.warn("created new user");

                            return done(null, newUser, req.flash('success', 'created new user'));
                        });
                    })
                }

            });

        }));

    // Use the FacebookStrategy within Passport.
    // Strategies in Passport require a `verify` function, which accept
    // credentials (in this case, an accessToken, refreshToken, and Facebook
    // profile), and invoke a callback with a user object.
    passport.use(new FacebookStrategy({
            clientID: FACEBOOK_APP_ID,
            clientSecret: FACEBOOK_APP_SECRET,
            callbackURL: "http://localhost:8080/auth/facebook/callback"
        },
        function(req, accessToken, refreshToken, profile, done) {
            // asynchronous verification, for effect...

            process.nextTick(function() {
                if (!req.user) {
                    User.findOne({ 'user.email': profile.emails[0].value }, function(err, user) {
                        if (err) {
                            return done(err);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            var newUser = new User();
                            newUser.user.username = profile.displayName;
                            newUser.user.email = profile.emails[0].value;
                            newUser.user.name = ''
                            newUser.user.address = ''

                            newUser.save(function(err) {
                                if (err)
                                    throw err;
                                return done(null, newUser);
                            });
                        }

                    });
                } else {
                    var user = req.user;
                    user.user.username = profile.displayName;
                    user.user.email = profile.emails[0].value;
                    user.user.name = ''
                    user.user.address = ''

                    user.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, user);
                    });
                }
            });
        }
    ));

    // Use the TwitterStrategy within Passport.
    // Strategies in passport require a `verify` function, which accept
    // credentials (in this case, a token, tokenSecret, and Twitter profile), and
    // invoke a callback with a user object.
    passport.use(new TwitterStrategy({
            consumerKey: TWITTER_CONSUMER_KEY,
            consumerSecret: TWITTER_CONSUMER_SECRET,
            callbackURL: "http://192.168.1.101:8080/auth/twitter/callback"
        },
        function(req, token, tokenSecret, profile, done) {
            // asynchronous verification, for effect...
            process.nextTick(function() {

                if (!req.user) {
                    User.findOne({ 'user.username': profile.displayName }, function(err, user) {
                        if (err) {
                            return done(err);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            var newUser = new User();
                            newUser.user.username = profile.displayName;
                            newUser.user.name = ''
                            newUser.user.address = ''

                            newUser.save(function(err) {
                                if (err)
                                    throw err;
                                return done(null, newUser);
                            });
                        }

                    });
                } else {
                    var user = req.user;
                    user.user.username = profile.displayName;
                    user.user.name = ''
                    user.user.address = ''

                    user.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, user);
                    });
                }
            });
        }
    ));

    // Use the GoogleStrategy within Passport.
    // Strategies in Passport require a `verify` function, which accept
    // credentials (in this case, an accessToken, refreshToken, and Google
    // profile), and invoke a callback with a user object.
    passport.use(new GoogleStrategy({
            clientID: GOOGLE_CONSUMER_KEY,
            clientSecret: GOOGLE_CONSUMER_SECRET,
            callbackURL: "http://localhost:8080/auth/google/callback"
        },
        function(req, accessToken, refreshToken, profile, done) {
            // asynchronous verification, for effect...
            process.nextTick(function() {

                if (!req.user) {
                    User.findOne({ 'user.email': profile.emails[0].value }, function(err, user) {
                        if (err) {
                            return done(err);
                        }
                        if (user) {
                            return done(null, user);
                        } else {
                            var newUser = new User();
                            newUser.user.username = profile.displayName;
                            newUser.user.email = profile.emails[0].value;
                            newUser.user.name = ''
                            newUser.user.address = ''

                            newUser.save(function(err) {
                                if (err)
                                    throw err;
                                return done(null, newUser);
                            });
                        }

                    });
                } else {
                    var user = req.user;
                    user.user.username = profile.displayName;
                    user.user.email = profile.emails[0].value;
                    user.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, user);
                    });
                }
            });

        }

    ));

};
<|endoftext|>