<commit_before>define(["js/data/Entity", "sprd/entity/ShippingState", "sprd/entity/Country", "sprd/entity/Person", "sprd/data/validator/LengthValidator", "js/data/validator/RegExValidator", "js/data/transformer/TrimTransformer", "js/data/validator/Validator", "underscore"], function (Entity, ShippingState, Country, Person, LengthValidator, RegExValidator, TrimTransformer, Validator, _) {

    var ADDRESS_TYPES = {
        PACKSTATION: "PACKSTATION",
        PRIVATE: "PRIVATE",
        UPS_PICKUP: "UPS_PICKUP"
    };

    var MAX_LENGTH = {
        STREET: 50,
        ZIP_CODE: 10,
        CITY: 30,
        STREET_ANNEX: 50
    };

    var MIN_LENGTH = {
        STREET: 3
    };

    var POSTNUMMER = "Postnummer ",
        PACKSTATION = "Packstation ";

    var VatValidator = Validator.inherit({
        _validate: function (entity) {
            var error = entity.fieldError(this.$.field);
            if (error && error.$.code == this.$.errorCode) {
                // return true of the field is empty
                return !entity.get(this.$.field) ? null : this._createFieldError(this.$.field);
            }
            return null;
        }
    });

    var StreetValidator = Validator.inherit({

        _validate: function (entity) {
            var value = entity.get(this.$.field);

            // if its HQ don't validate
            if (value && !/^HQ/.test(value)) {
                // validate minlength, maxlength and that it contains a number
                if (value.length < MIN_LENGTH.STREET || value.length > MAX_LENGTH.STREET ||
                    (!/\d/.test(value) && _.indexOf(["GB", "FR", "IE", "GG", "ES"], entity.get("country.code")) === -1)
                ) {
                    return this._createFieldError(this.$.field);
                }
            }
        }

    });

    var PackStationValidation = RegExValidator.inherit({
        _validate: function(entity, option) {
            option = option || {};

            if ((option.validationOptions || {}).skipPackStationValidation === true) {
                return;
            }

            return this.callBase();

        }
    });

    var Address = Entity.inherit("sprd.entity.Address", {

        defaults: {
            type: ADDRESS_TYPES.PRIVATE,
            company: null,
            person: Person,
            isBillingAddress: false,
            street: null,
            streetAnnex: null,
            houseNumber: null,
            city: null,
            state: null,
            country: null,
            zipCode: null,
            email: null,
            phone: null,
            fax: null,
            packStationNr: "",
            postNr: "",
            personSalutation: "{person.salutation}",
            isSameAsBillingAddress: true,
            root: null,
            shippingCountries: "{root.shippingCountries()}"
        },

        schema: {
            type: {
                type: String,
                required: true
            },
            company: {
                type: String,
                required: function () {
                    return this.isCompany();
                }
            },

            vatId: {
                type: String,
                required: false
            },

            person: Person,

            street: {
                type: String,
                required: function () {
                    return !this.isPackStation();
                }
            },

            streetAnnex: {
                type: String,
                required: false
            },
            city: String,
            houseNumber: {
                type: String,
                required: false
            },
            state: {
                isReference: true,
                type: ShippingState,
                required: function () {
                    return this.isStateRequired();
                }
            },
            country: {
                type: Country,
                isReference: true
            },
            zipCode: {
                type: String,
                required: function () {
                    // not required for Ireland
                    return this.needsZipCode();
                }
            },
            postNr: {
                type: String,
                required: function () {
                    return this.isPackStation()
                }
            },

            packStationNr: {
                type: String,
                required: function () {
                    return this.isPackStation()
                }
            },

            phone: {
                type: String,
                required: false
            },
            fax: {
                type: String,
                required: false
            }
        },

        transformers: [
            new TrimTransformer()
        ],

        validators: [
            new LengthValidator({
                field: "zipCode",
                maxLength: MAX_LENGTH.ZIP_CODE
            }),
            new LengthValidator({
                field: "city",
                maxLength: MAX_LENGTH.CITY
            }),
            new LengthValidator({
                field: "streetAnnex",
                maxLength: MAX_LENGTH.STREET_ANNEX
            }),
            new RegExValidator({
                field: "street",
                regEx: /postfiliale/i,
                inverse: true,
                errorCode: "postfilialeNotSupported"
            }),
            new PackStationValidation({
                field: "street",
                regEx: /packstation|postnummer/i,
                inverse: true,
                errorCode: "packstationError"
            }),
            new StreetValidator({
                field: "street",
                errorCode: "wrongFormat"
            }),
            new VatValidator({
                field: "vatId",
                errorCode: "vatIdError"
            })
        ],

        _commitChangedAttributes: function ($) {
            this.callBase();

            if ($.hasOwnProperty("country") && this.$.type === ADDRESS_TYPES.PACKSTATION) {
                if ($.country.get('code') != "DE") {
                    this.set('type', ADDRESS_TYPES.PRIVATE);
                }
            }
            if ($.hasOwnProperty("country")) {
                if (!this.isStateRequired()) {
                    this.set('state', null);
                }

                if ($.country && $.country.$.code === "AU" && this.get("person.salutation") == 4) {
                    // company to australia is forbidden, see DEV-134352
                    this.$.person.set("salutation", null);
                }
            }
        },

        _commitVatId: function (vatId) {
            if (vatId && this.fieldError("vatId")) {
                this.$errors.unset('vatId');
            }
        },

        _commitCountry: function (country) {
            if (country && this.fieldError("vatId")) {
                this.$errors.unset("vatId");
            }
        },

        _commitPersonSalutation: function (salutation) {
            if (salutation === Person.Salutation.COMPANY) {
                this.set('type', ADDRESS_TYPES.PRIVATE);
            }
        },

        parse: function (data) {
            if (data.type === ADDRESS_TYPES.PACKSTATION) {
                data.packStationNr = data.street ? data.street.replace(PACKSTATION, "") : "";
                data.postNr = data.streetAnnex ? data.streetAnnex.replace(POSTNUMMER, "") : "";
                delete data.streetAnnex;
                delete data.street;
            }

            return this.callBase(data);
        },

        compose: function () {
            var data = this.callBase();

            if (!this.isStateRequired()) {
                delete data.state;
            }

            if (!this.needsZipCode() && !data.zipCode) {
                data.zipCode = "-";
            }

            if (this.get('type') === ADDRESS_TYPES.PACKSTATION) {
                data.street = PACKSTATION + (data.packStationNr || "").replace(/packstation/i, " ").replace(/^\s*|\s*$/, "");
                data.streetAnnex = POSTNUMMER + data.postNr;
            } else {
                delete data.packStationNr;
                delete data.postNr;
            }

            if (!this.isCompany()) {
                delete data.company;
                delete data.vatId;
            } else if (data.vatId && !/^[A-Z]{2}/.test(data.vatId)) {
                data.vatId = (this.get("country.code") || "").toUpperCase() + data.vatId.replace(/^[A-Z]*/, "");
                console.dir(data);
            }

            // send empty house number
            data.houseNumber = "";

            return data;
        },

        needsVatId: function (platform) {
            return platform == "EU" && this.isCompany() && (this.$.isBillingAddress || this.$.isSameAsBillingAddress);
        }.onChange('personSalutation', 'isBillingAddress', 'isSameAsBillingAddress'),

        isPrivate: function() {
            return this.$.type == ADDRESS_TYPES.PRIVATE;
        }.onChange('type'),

        isPackStation: function () {
            return this.$.type == ADDRESS_TYPES.PACKSTATION;
        }.onChange('type'),

        isUpsPickup: function() {
            return this.$.type == ADDRESS_TYPES.UPS_PICKUP;
        }.onChange('type'),

        supportsPackStation: function () {
            return this.$.personSalutation !== Person.Salutation.COMPANY && this.get('country.code') === "DE" && !this.$.isBillingAddress;
        }.onChange('country.code', 'personSalutation', 'isBillingAddress'),

        supportsUpsPickup: function() {
            return this.$.personSalutation !== Person.Salutation.COMPANY && this.get('country.code') === "FR" && !this.$.isBillingAddress;
        }.onChange('country.code', 'personSalutation', 'isBillingAddress'),

        needsCounty: function () {
            return  this.get('country.code') === "IE";
        }.onChange('country'),

        hasStates: function () {
            return this.get("country.shippingStates.length") > 0
        }.onChange("country"),

        isStateRequired: function () {
            return  ["US", "CA"].indexOf(this.get('country.code')) > -1;
        }.onChange('country'),

        needsZipCode: function () {
            // not required for ireland
            return this.get("country.code") !== "IE";
        }.onChange('country'),

        isCompany: function () {
            return this.$.personSalutation === Person.Salutation.COMPANY
        }.onChange('personSalutation'),

        isEqual: function (address) {
            if (!address) {
                return false;
            }
            var field,
                fields = ["type", "company", "vatId", "person.firstName", "person.lastName", "person.salutation", "street", "streetAnnex", "city", "state.code", "country.code", "zipCode", "postNr", "packStationNr", "phone", "fax"];

            for (var i = 0; i < fields.length; i++) {
                field = fields[i];
                var value = this.get(field),
                    compare = address.get(field);

                if (value && value.isEqual) {
                    if (!value.isEqual(compare)) {
                        return false;
                    }
                } else {
                    if (value !== compare) {
                        return false;
                    }
                }
            }
            return true;
        }
    });

    Address.ADDRESS_TYPES = ADDRESS_TYPES;
    Address.MAX_LENGTH = MAX_LENGTH;

    return Address;
});
<commit_msg>first version of UPS<commit_after>define(["js/data/Entity", "sprd/entity/ShippingState", "sprd/entity/Country", "sprd/entity/Person", "sprd/data/validator/LengthValidator", "js/data/validator/RegExValidator", "js/data/transformer/TrimTransformer", "js/data/validator/Validator", "underscore"], function (Entity, ShippingState, Country, Person, LengthValidator, RegExValidator, TrimTransformer, Validator, _) {

    var ADDRESS_TYPES = {
        PACKSTATION: "PACKSTATION",
        PRIVATE: "PRIVATE",
        UPS_PICKUP: "UPS_PICKUP"
    };

    var MAX_LENGTH = {
        STREET: 50,
        ZIP_CODE: 10,
        CITY: 30,
        STREET_ANNEX: 50
    };

    var MIN_LENGTH = {
        STREET: 3
    };

    var POSTNUMMER = "Postnummer ",
        PACKSTATION = "Packstation ";

    var VatValidator = Validator.inherit({
        _validate: function (entity) {
            var error = entity.fieldError(this.$.field);
            if (error && error.$.code == this.$.errorCode) {
                // return true of the field is empty
                return !entity.get(this.$.field) ? null : this._createFieldError(this.$.field);
            }
            return null;
        }
    });

    var StreetValidator = Validator.inherit({

        _validate: function (entity) {
            var value = entity.get(this.$.field);

            // if its HQ don't validate
            if (value && !/^HQ/.test(value)) {
                // validate minlength, maxlength and that it contains a number
                if (value.length < MIN_LENGTH.STREET || value.length > MAX_LENGTH.STREET ||
                    (!/\d/.test(value) && _.indexOf(["GB", "FR", "IE", "GG", "ES"], entity.get("country.code")) === -1)
                ) {
                    return this._createFieldError(this.$.field);
                }
            }
        }

    });

    var PackStationValidation = RegExValidator.inherit({
        _validate: function(entity, option) {
            option = option || {};

            if ((option.validationOptions || {}).skipPackStationValidation === true) {
                return;
            }

            return this.callBase();

        }
    });

    var Address = Entity.inherit("sprd.entity.Address", {

        defaults: {
            type: ADDRESS_TYPES.PRIVATE,
            company: null,
            person: Person,
            isBillingAddress: false,
            street: null,
            streetAnnex: null,
            houseNumber: null,
            city: null,
            state: null,
            country: null,
            zipCode: null,
            email: null,
            phone: null,
            fax: null,
            packStationNr: "",
            postNr: "",
            personSalutation: "{person.salutation}",
            isSameAsBillingAddress: true,
            root: null,
            shippingCountries: "{root.shippingCountries()}"
        },

        schema: {
            type: {
                type: String,
                required: true
            },
            company: {
                type: String,
                required: function () {
                    return this.isCompany();
                }
            },

            vatId: {
                type: String,
                required: false
            },

            person: Person,

            street: {
                type: String,
                required: function () {
                    return this.isPrivate();
                }
            },
            streetAnnex: {
                type: String,
                required: false
            },
            city: {
                type: String,
                required: function() {
                    return this.isPrivate();
                }
            },
            houseNumber: {
                type: String,
                required: false
            },
            state: {
                isReference: true,
                type: ShippingState,
                required: function () {
                    return this.isPrivate() && this.isStateRequired();
                }
            },
            country: {
                type: Country,
                isReference: true
            },
            zipCode: {
                type: String,
                required: function () {
                    // not required for Ireland
                    return this.isPrivate() && this.needsZipCode();
                }
            },

            postNr: {
                type: String,
                required: function () {
                    return this.isPackStation()
                }
            },

            packStationNr: {
                type: String,
                required: function () {
                    return this.isPackStation()
                }
            },

            ups: {
                type: Object,
                required: function() {
                    return this.isUpsPickup()
                }
            },

            phone: {
                type: String,
                required: false
            },
            fax: {
                type: String,
                required: false
            }
        },

        transformers: [
            new TrimTransformer()
        ],

        validators: [
            new LengthValidator({
                field: "zipCode",
                maxLength: MAX_LENGTH.ZIP_CODE
            }),
            new LengthValidator({
                field: "city",
                maxLength: MAX_LENGTH.CITY
            }),
            new LengthValidator({
                field: "streetAnnex",
                maxLength: MAX_LENGTH.STREET_ANNEX
            }),
            new RegExValidator({
                field: "street",
                regEx: /postfiliale/i,
                inverse: true,
                errorCode: "postfilialeNotSupported"
            }),
            new PackStationValidation({
                field: "street",
                regEx: /packstation|postnummer/i,
                inverse: true,
                errorCode: "packstationError"
            }),
            new StreetValidator({
                field: "street",
                errorCode: "wrongFormat"
            }),
            new VatValidator({
                field: "vatId",
                errorCode: "vatIdError"
            })
        ],

        _commitChangedAttributes: function ($) {
            this.callBase();

            if ($.hasOwnProperty("country") && this.$.type === ADDRESS_TYPES.PACKSTATION) {
                if ($.country.get('code') != "DE") {
                    this.set('type', ADDRESS_TYPES.PRIVATE);
                }
            }

            if ($.hasOwnProperty("country")) {
                if (!this.isStateRequired()) {
                    this.set('state', null);
                }

                if ($.country && $.country.$.code === "AU" && this.get("person.salutation") == 4) {
                    // company to australia is forbidden, see DEV-134352
                    this.$.person.set("salutation", null);
                }
            }
        },

        _commitVatId: function (vatId) {
            if (vatId && this.fieldError("vatId")) {
                this.$errors.unset('vatId');
            }
        },

        _commitCountry: function (country) {
            if (country && this.fieldError("vatId")) {
                this.$errors.unset("vatId");
            }
        },

        _commitPersonSalutation: function (salutation) {
            if (salutation === Person.Salutation.COMPANY) {
                this.set('type', ADDRESS_TYPES.PRIVATE);
            }
        },

        parse: function (data) {
            if (data.type === ADDRESS_TYPES.PACKSTATION) {
                data.packStationNr = data.street ? data.street.replace(PACKSTATION, "") : "";
                data.postNr = data.streetAnnex ? data.streetAnnex.replace(POSTNUMMER, "") : "";
                delete data.streetAnnex;
                delete data.street;
            } else if (data.type === ADDRESS_TYPES.UPS_PICKUP) {
                delete data.street;
                delete data.company;
                delete data.zipCode;
            }

            return this.callBase(data);
        },

        compose: function () {
            var data = this.callBase();

            if (!this.isStateRequired()) {
                delete data.state;
            }

            if (!this.needsZipCode() && !data.zipCode) {
                data.zipCode = "-";
            }

            var type = this.get('type');

            if (!this.isCompany()) {
                delete data.company;
                delete data.vatId;
            } else if (data.vatId && !/^[A-Z]{2}/.test(data.vatId)) {
                data.vatId = (this.get("country.code") || "").toUpperCase() + data.vatId.replace(/^[A-Z]*/, "");
            }

            if (type === ADDRESS_TYPES.PACKSTATION) {
                data.street = PACKSTATION + (data.packStationNr || "").replace(/packstation/i, " ").replace(/^\s*|\s*$/, "");
                data.streetAnnex = POSTNUMMER + data.postNr;
            } else if (type === ADDRESS_TYPES.UPS_PICKUP) {
                var ups = data.ups;
                data.street = ups.street;
                data.company = ups.company;
                data.city = ups.city;
                data.zipCode = ups.zipCode;
            }

            delete data.packStationNr;
            delete data.postNr;
            delete data.ups;

            // send empty house number
            data.houseNumber = "";

            return data;
        },

        needsVatId: function (platform) {
            return platform == "EU" && this.isCompany() && (this.$.isBillingAddress || this.$.isSameAsBillingAddress);
        }.onChange('personSalutation', 'isBillingAddress', 'isSameAsBillingAddress'),

        isPrivate: function() {
            return this.$.type == ADDRESS_TYPES.PRIVATE;
        }.onChange('type'),

        isPackStation: function () {
            return this.$.type == ADDRESS_TYPES.PACKSTATION;
        }.onChange('type'),

        isUpsPickup: function() {
            return this.$.type == ADDRESS_TYPES.UPS_PICKUP;
        }.onChange('type'),

        supportsPackStation: function () {
            return this.$.personSalutation !== Person.Salutation.COMPANY && this.get('country.code') === "DE" && !this.$.isBillingAddress;
        }.onChange('country.code', 'personSalutation', 'isBillingAddress'),

        supportsUpsPickup: function() {
            return this.$.personSalutation !== Person.Salutation.COMPANY && this.get('country.code') === "FR" && !this.$.isBillingAddress;
        }.onChange('country.code', 'personSalutation', 'isBillingAddress'),

        needsCounty: function () {
            return  this.get('country.code') === "IE";
        }.onChange('country'),

        hasStates: function () {
            return this.get("country.shippingStates.length") > 0
        }.onChange("country"),

        isStateRequired: function () {
            return  ["US", "CA"].indexOf(this.get('country.code')) > -1;
        }.onChange('country'),

        needsZipCode: function () {
            // not required for ireland
            return this.get("country.code") !== "IE";
        }.onChange('country'),

        isCompany: function () {
            return this.$.personSalutation === Person.Salutation.COMPANY
        }.onChange('personSalutation'),

        isEqual: function (address) {
            if (!address) {
                return false;
            }
            var field,
                fields = ["type", "company", "vatId", "person.firstName", "person.lastName", "person.salutation", "street", "streetAnnex", "city", "state.code", "country.code", "zipCode", "postNr", "packStationNr", "phone", "fax"];

            for (var i = 0; i < fields.length; i++) {
                field = fields[i];
                var value = this.get(field),
                    compare = address.get(field);

                if (value && value.isEqual) {
                    if (!value.isEqual(compare)) {
                        return false;
                    }
                } else {
                    if (value !== compare) {
                        return false;
                    }
                }
            }
            return true;
        }
    });

    Address.ADDRESS_TYPES = ADDRESS_TYPES;
    Address.MAX_LENGTH = MAX_LENGTH;

    return Address;
});
<|endoftext|>


<commit_before>define(["sprd/data/SprdModel", "sprd/model/PaymentType", "sprd/entity/Payment", "underscore", "rAppid", "flow", "js/data/Entity"], function(SprdModel, PaymentType, Payment, _, rAppid, flow, Entity) {

    var BrowserInformation = Entity.inherit({

        schema: {
            colorDepth: Number,
            screenWidth: Number,
            screenHeight: Number,
            timeZoneOffset: Number,
            javaEnabled: Boolean
        },

        ctor: function() {
            this.callBase({
                colorDepth: screen.colorDepth,
                screenWidth: screen.width,
                screenHeight: screen.height,
                timeZoneOffset: (new Date()).getTimezoneOffset(),
                javaEnabled: navigator.javaEnabled ? navigator.javaEnabled() : false
            })
        },

    });

    var AdyenData = Entity.inherit('sprd.model.Checkout.CheckoutResult', {
        schema: {
            pendingPaymentId: {
                type: String,
                required: false
            },
            threeDSMethodUrl: {
                type: String,
                required: false
            },
            adyen3dSecure2EndUrl: {
                type: String,
                required: false
            },
            threeDSServerTransId: {
                type: String,
                required: false
            }
        }
    });

    var CheckoutResult = Entity.inherit('sprd.model.Checkout.CheckoutResult', {
        schema: {
            redirectUrl: {
                type: String,
                required: false
            },
            data: {
                type: AdyenData,
                required: false
            }
        }
    });

    var CreditCardCheckout = SprdModel.inherit("sprd.model.Checkout.CreditCard", {

        $isDependentObject: true,

        resultType: CheckoutResult,

        schema: {
            paymentType: PaymentType,
            payment: Payment,
            browserInformation: BrowserInformation,
            returnUrl: String
        },

        defaults: {
            browserInformation: BrowserInformation
        }

    });

    var AuthorizationData = Entity.inherit('sprd.model.Checkout.AuthorizationData', {
        schema: {
            serverTransactionId: String,
            acsTransactionId: String,
            acsUrl: String,
            messageVersion: String
        }
    });

    var Authorize3dsResult = Entity.inherit('sprd.model.Checkout.CheckoutResult', {
        redirectUrl: {
            type: String,
            required: false
        },
        data: {
            type: AuthorizationData,
            required: false
        }
    });

    var Authorize3ds = SprdModel.inherit("sprd.model.Checkout.Authorize3ds", {

        $isDependentObject: true,

        resultType: Authorize3dsResult,

        defaults: {
            pendingPaymentId: null,
            indicator: null
        },

        schema: {
            pendingPaymentId: String,
            indicator: String
        }
    });

    return SprdModel.inherit("sprd.model.Checkout", {

        defaults: {
            paymentType: null,
            payment: null,
            returnUrl: null,
            fingerPrint: null
        },

        $isDependentObject: true,

        schema: {
            paymentType: PaymentType,
            payment: Payment,
            returnUrl: String
        },

        save: function(callback) {

            var self = this,
                payment = this.$.payment;

            flow()
                .seq(function(cb) {
                    if (!payment) {
                        return cb();
                    }
                    payment._beforeCompose(cb);
                })
                .seq("result", function(cb) {

                    if (self.get('paymentType.categoryCode') == 'CREDITCARD') {

                        var model = self.$context.$contextModel.createEntity(CreditCardCheckout);
                        model.set(self.$);
                        model.set("id", null);

                        model.save(null, cb);
                    } else {
                        self.doFormPost();
                        cb();
                    }
                })
                .exec(function(err, data) {
                    callback && callback(err, data.result);
                });

        },

        authorize3ds: function(pendingPaymentId, indicator, callback) {
            var model = this.$context.$contextModel.createEntity(Authorize3ds);

            model.set({
                pendingPaymentId: pendingPaymentId,
                indicator: indicator
            });

            model.save(null, callback);
        },

        doFormPost: function() {

            var dataSource = this.$context.$dataSource,
                parameter  = {};

            var url = dataSource._buildUriForResource(this);

            _.defaults(parameter, this.$context.getQueryParameters(), dataSource.getQueryParameters("put", this));
            delete parameter.mediaType;

            url += "?" + rAppid.createQueryString(parameter);

            var processor = dataSource.getProcessorForModel(this);
            var formatProcessor = dataSource.getFormatProcessor("save", this);

            var checkoutData = processor.compose(this, "save");

            var fingerPrint = this.$.fingerPrint;
            if (fingerPrint && checkoutData.payment) {
                checkoutData.payment.fingerPrint = fingerPrint;
            }

            var data = formatProcessor.serialize(checkoutData);
            this.doFormPost(url, data);

            var form = document.createElement("form");
            form.setAttribute("method", "post");
            form.setAttribute("action", url);

            if (this.inIframe()) {
                // do a navigation on the top frame, this
                // could fail if a sandbox is defined without allow-top-navigation.

                // to be more secure, we could just add this _top target, where we know
                // that the loading checkout don't allow to run within an iframe
                // (X-Frame-Options, see https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options),
                // which is the case for e.g. paypal
                form.setAttribute("target", "_top");
            }

            var valueField = document.createElement("input");
            valueField.setAttribute("type", "hidden");
            valueField.setAttribute("name", "value");
            valueField.setAttribute("enctype", "multipart/form-data");
            valueField.setAttribute("value", data);

            form.appendChild(valueField);
            document.body.appendChild(form);
            form.submit();
        },

        inIframe: function() {
            try {
                return window.self !== window.top;
            } catch (e) {
                return true;
            }
        },

        compose: function () {
            var ret = this.callBase();

            ret.payment = ret.payment || {};
            ret.paymentType = ret.paymentType || {};

            return ret;
        }

    });

});<commit_msg>[DEV-144301] - Buy button is not working<commit_after>define(["sprd/data/SprdModel", "sprd/model/PaymentType", "sprd/entity/Payment", "underscore", "rAppid", "flow", "js/data/Entity"], function(SprdModel, PaymentType, Payment, _, rAppid, flow, Entity) {

    var BrowserInformation = Entity.inherit({

        schema: {
            colorDepth: Number,
            screenWidth: Number,
            screenHeight: Number,
            timeZoneOffset: Number,
            javaEnabled: Boolean
        },

        ctor: function() {
            this.callBase({
                colorDepth: screen.colorDepth,
                screenWidth: screen.width,
                screenHeight: screen.height,
                timeZoneOffset: (new Date()).getTimezoneOffset(),
                javaEnabled: navigator.javaEnabled ? navigator.javaEnabled() : false
            })
        },

    });

    var AdyenData = Entity.inherit('sprd.model.Checkout.CheckoutResult', {
        schema: {
            pendingPaymentId: {
                type: String,
                required: false
            },
            threeDSMethodUrl: {
                type: String,
                required: false
            },
            adyen3dSecure2EndUrl: {
                type: String,
                required: false
            },
            threeDSServerTransId: {
                type: String,
                required: false
            }
        }
    });

    var CheckoutResult = Entity.inherit('sprd.model.Checkout.CheckoutResult', {
        schema: {
            redirectUrl: {
                type: String,
                required: false
            },
            data: {
                type: AdyenData,
                required: false
            }
        }
    });

    var CreditCardCheckout = SprdModel.inherit("sprd.model.Checkout.CreditCard", {

        $isDependentObject: true,

        resultType: CheckoutResult,

        schema: {
            paymentType: PaymentType,
            payment: Payment,
            browserInformation: BrowserInformation,
            returnUrl: String
        },

        defaults: {
            browserInformation: BrowserInformation
        }

    });

    var AuthorizationData = Entity.inherit('sprd.model.Checkout.AuthorizationData', {
        schema: {
            serverTransactionId: String,
            acsTransactionId: String,
            acsUrl: String,
            messageVersion: String
        }
    });

    var Authorize3dsResult = Entity.inherit('sprd.model.Checkout.CheckoutResult', {
        redirectUrl: {
            type: String,
            required: false
        },
        data: {
            type: AuthorizationData,
            required: false
        }
    });

    var Authorize3ds = SprdModel.inherit("sprd.model.Checkout.Authorize3ds", {

        $isDependentObject: true,

        resultType: Authorize3dsResult,

        defaults: {
            pendingPaymentId: null,
            indicator: null
        },

        schema: {
            pendingPaymentId: String,
            indicator: String
        }
    });

    return SprdModel.inherit("sprd.model.Checkout", {

        defaults: {
            paymentType: null,
            payment: null,
            returnUrl: null,
            fingerPrint: null
        },

        $isDependentObject: true,

        schema: {
            paymentType: PaymentType,
            payment: Payment,
            returnUrl: String
        },

        save: function(callback) {

            var self = this,
                payment = this.$.payment;

            flow()
                .seq(function(cb) {
                    if (!payment) {
                        return cb();
                    }
                    payment._beforeCompose(cb);
                })
                .seq("result", function(cb) {

                    if (self.get('paymentType.categoryCode') == 'CREDITCARD') {

                        var model = self.$context.$contextModel.createEntity(CreditCardCheckout);
                        model.set(self.$);
                        model.set("id", null);

                        model.save(null, cb);
                    } else {
                        self.doFormPost();
                        cb();
                    }
                })
                .exec(function(err, data) {
                    callback && callback(err, data.result);
                });

        },

        authorize3ds: function(pendingPaymentId, indicator, callback) {
            var model = this.$context.$contextModel.createEntity(Authorize3ds);

            model.set({
                pendingPaymentId: pendingPaymentId,
                indicator: indicator
            });

            model.save(null, callback);
        },

        doFormPost: function() {

            var dataSource = this.$context.$dataSource,
                parameter  = {};

            var url = dataSource._buildUriForResource(this);

            _.defaults(parameter, this.$context.getQueryParameters(), dataSource.getQueryParameters("put", this));
            delete parameter.mediaType;

            url += "?" + rAppid.createQueryString(parameter);

            var processor = dataSource.getProcessorForModel(this);
            var formatProcessor = dataSource.getFormatProcessor("save", this);

            var checkoutData = processor.compose(this, "save");

            var fingerPrint = this.$.fingerPrint;
            if (fingerPrint && checkoutData.payment) {
                checkoutData.payment.fingerPrint = fingerPrint;
            }

            var data = formatProcessor.serialize(checkoutData);

            var form = document.createElement("form");
            form.setAttribute("method", "post");
            form.setAttribute("action", url);

            if (this.inIframe()) {
                // do a navigation on the top frame, this
                // could fail if a sandbox is defined without allow-top-navigation.

                // to be more secure, we could just add this _top target, where we know
                // that the loading checkout don't allow to run within an iframe
                // (X-Frame-Options, see https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options),
                // which is the case for e.g. paypal
                form.setAttribute("target", "_top");
            }

            var valueField = document.createElement("input");
            valueField.setAttribute("type", "hidden");
            valueField.setAttribute("name", "value");
            valueField.setAttribute("enctype", "multipart/form-data");
            valueField.setAttribute("value", data);

            form.appendChild(valueField);
            document.body.appendChild(form);
            form.submit();
        },

        inIframe: function() {
            try {
                return window.self !== window.top;
            } catch (e) {
                return true;
            }
        },

        compose: function () {
            var ret = this.callBase();

            ret.payment = ret.payment || {};
            ret.paymentType = ret.paymentType || {};

            return ret;
        }

    });

});<|endoftext|>


<commit_before>// routing

Router.configure({ layoutTemplate: 'main' });

Router.map(function () {
  this.route('login');
  this.route('code', { path: '/', });
  this.route('test');
  this.route('git');
  this.route('config');
  this.route('renderer', {layoutTemplate: 'null' });
  this.route('raw', {layoutTemplate: 'null' });
});

// accepting screenshots at the feedback url
// curl --data "lat=12&lon=14" http://localhost:3000/feedback

Router.route('feedback', {
  path: '/feedback/',
  where: 'server',
  action: function addIssue() {
    var issue = JSON.parse( this.request.body.feedback );
    if(Meteor.users.findOne(issue.user)) // dont take junk
      Meteor.call('addIssue', issue);
  }
});

// serving feedback images, from id

Router.route('screenshot/:_id', {
  name: 'screenshot',
  layoutTemplate: 'null',
  onBeforeAction: null,
  action: function viewScreen() {
    var img = Screens.findOne(this.params._id);
    this.render('screenshot', {data: img});
  }
});

// ask user to login before coding, only on client

Router.onBeforeAction(function preLogin() {
  if (! Meteor.userId() || Meteor.loggingIn()){
    this.layout('login');
    this.render('login');
  }else
    this.next();
}, {except: ['login', 'screenshot']}); // but allow anybody to check issue imgs
<commit_msg>fix feedback - needs on before only on client<commit_after>// routing

Router.configure({ layoutTemplate: 'main' });

Router.map(function () {
  this.route('login');
  this.route('code', { path: '/', });
  this.route('test');
  this.route('git');
  this.route('config');
  this.route('renderer', {layoutTemplate: 'null' });
  this.route('raw', {layoutTemplate: 'null' });
});

// accepting screenshots at the feedback url
// curl --data "lat=12&lon=14" http://localhost:3000/feedback

Router.route('feedback', {
  path: '/feedback/',
  where: 'server',
  action: function addIssue() {
    var issue = JSON.parse( this.request.body.feedback );
    if(Meteor.users.findOne(issue.user)) // dont take junk
      Meteor.call('addIssue', issue);
  }
});

// serving feedback images, from id

Router.route('screenshot/:_id', {
  name: 'screenshot',
  layoutTemplate: 'null',
  onBeforeAction: null,
  action: function viewScreen() {
    var img = Screens.findOne(this.params._id);
    this.render('screenshot', {data: img});
  }
});

// ask user to login before coding, only on client

if(Meteor.isClient){
  Router.onBeforeAction(function preLogin() {
    if (! Meteor.userId() || Meteor.loggingIn()){
      this.layout('login');
      this.render('login');
    }else
      this.next();
  }, {except: ['login', 'screenshot']}); // but allow anybody to check issue imgs
}
<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.login', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {

}])

.controller('LoginCtrl', ['$rootScope', function($rootScope){

  // Check if the Facebook API is already initialized
  if (window.fbAsyncInit) {
    console.log('Already Initialized FB', window.FB);
    checkLoginState();
  } else {
    initFB();
  }

  function statusChangeCallback(response) {
    console.log('statusChangeCallback: ',response);
    // The response object is returned with a status field that lets the
    // app know the current login status of the person.
    // Full docs on the response object can be found in the documentation
    // for FB.getLoginStatus().
    if (response.status === 'connected') {
      // Logged into your app and Facebook.
      console.log('connected: ',response);
      showLogoutButton();
      getUser();
      $rootScope.FB = FB;
      $rootScope.hosts = [];
      init();

    } else if (response.status === 'not_authorized') {
      // The person is logged into Facebook, but not your app.
      document.getElementById('status').innerHTML = 'Please log ' +
        'into this app.';
    } else {
      // The person is not logged into Facebook, so we're not sure if
      // they are logged into this app or not.
      document.getElementById('status').innerHTML = 'Please log ' +
        'into Facebook.';
    }
  }

  // This function is called when someone finishes with the Login
  // Button.  See the onlogin handler attached to it in the sample
  // code below.
  function checkLoginState() {
    FB.getLoginStatus(function(response) {
      statusChangeCallback(response);
    });
  }

  function initFB() {
    window.fbAsyncInit = function() {
    FB.init({
      appId      : '1030020633759691',
      cookie     : true,  // enable cookies to allow the server to access
                          // the session
      xfbml      : true,  // parse social plugins on this page
      version    : 'v2.5' // use graph api version 2.5
    });

    // Now that we've initialized the JavaScript SDK, we call
    // FB.getLoginStatus().  This function gets the state of the
    // person visiting this page and can return one of three states to
    // the callback you provide.  They can be:
    //
    // 1. Logged into your app ('connected')
    // 2. Logged into Facebook, but not your app ('not_authorized')
    // 3. Not logged into Facebook and can't tell if they are logged into
    //    your app or not.
    //
    // These three cases are handled in the callback function.

    FB.getLoginStatus(function(response) {
      statusChangeCallback(response);
    });

    };
  }

  // Load the SDK asynchronously
  (function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));

}]);
<commit_msg>remove Facebook init<commit_after>'use strict';

angular.module('myApp.login', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {

}])

.controller('LoginCtrl', ['$rootScope', function($rootScope){

}]);
<|endoftext|>


<commit_before>"use strict";
angular.module('myApp.login', ['firebase.utils', 'firebase.auth', 'ngRoute'])

  .config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/login', {
      controller: 'LoginCtrl',
      templateUrl: 'login/login.html'
    });
  }])

  .controller('LoginCtrl', ['$scope', '$firebaseObject', 'FBURL', 'Auth', '$location', 'fbutil', function($scope, $firebaseObject, FBURL, Auth, $location, fbutil) {
    $scope.email = null;
    $scope.pass = null;

    $scope.login = function(email, pass) {
      Auth.$authWithOAuthPopup('google', {scope:'email'})
          .then(function (authObject) {
            //console.log(authObject);
            ////var ref = fbutil.ref('users', authObject.uid);
            //var ref = fbutil.ref('users', authObject.uid);
            //var obj = $firebaseObject(ref);
            //
            //
            //obj.foo = "bar";
            //obj.$save();

            //return fbutil.handler(function(cb) {
            //  ref.set({email: authObject.google.email, name: authObject.google.cachedUserProfile.name}, cb);
            //});

            var ref = new $window.Firebase(FBURL);
            var obj = $firebaseObject(ref);
            // to take an action after the data loads, use the $loaded() promise
            obj.$loaded().then(function(){
              console.log("loaded record:", obj.$id, obj.someOtherKeyInData);

              // To iterate the key/value pairs of the object, use angular.forEach()
              angular.forEach(obj, function(value, key){
                console.log(key, value);
              });
            });
          })
          .then(function(/* user */) {
            // redirect to the account page
            var authdata = Auth.$getAuth();
            console.log('Login UID = '+authdata.uid);
            $location.path('/account');
          }, function(err) {
            $scope.err = errMessage(err);
          });
    };
  }]);<commit_msg>no message<commit_after>"use strict";
angular.module('myApp.login', ['firebase.utils', 'firebase.auth', 'ngRoute'])

  .config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/login', {
      controller: 'LoginCtrl',
      templateUrl: 'login/login.html'
    });
  }])

  .controller('LoginCtrl', ['$scope', '$firebaseObject', 'FBURL', 'Auth', '$location', 'fbutil', function($scope, $firebaseObject, FBURL, Auth, $location, fbutil) {
    $scope.email = null;
    $scope.pass = null;

    $scope.login = function(email, pass) {
      Auth.$authWithOAuthPopup('google', {scope:'email'})
          .then(function (authObject) {
            //console.log(authObject);
            ////var ref = fbutil.ref('users', authObject.uid);
            //var ref = fbutil.ref('users', authObject.uid);
            //var obj = $firebaseObject(ref);
            //
            //
            //obj.foo = "bar";
            //obj.$save();

            //return fbutil.handler(function(cb) {
            //  ref.set({email: authObject.google.email, name: authObject.google.cachedUserProfile.name}, cb);
            //});

            var ref = new Firebase(FBURL);
            var obj = $firebaseObject(ref);
            // to take an action after the data loads, use the $loaded() promise
            obj.$loaded().then(function(){
              console.log("loaded record:", obj.$id);

              // To iterate the key/value pairs of the object, use angular.forEach()
              angular.forEach(obj, function(value, key){
                console.log(key, value);
              });
            });
          })
          .then(function(/* user */) {
            // redirect to the account page
            var authdata = Auth.$getAuth();
            console.log('Login UID = '+authdata.uid);
            $location.path('/account');
          }, function(err) {
            $scope.err = errMessage(err);
          });
    };
  }]);<|endoftext|>


<commit_before>/*! codeFormatter v0.1.0 by ryanpcmcquen */
//
// Ryan P.C. McQuen | Everett, WA | ryan.q@linux.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version, with the following exception:
// the text of the GPL license may be omitted.
//
// This program is distributed in the hope that it will be useful, but
// without any warranty; without even the implied warranty of
// merchantability or fitness for a particular purpose. Compiling,
// interpreting, executing or merely reading the text of the program
// may result in lapses of consciousness and/or very being, up to and
// including the end of all existence and the Universe as we know it.
// See the GNU General Public License for more details.
//
// You may have received a copy of the GNU General Public License along
// with this program (most likely, a file named COPYING).  If not, see
// <https://www.gnu.org/licenses/>.

/*global window*/
/*jslint browser:true, white:true*/
(function () {

  'use strict';

  var codeFormatter = function (selector) {
    var replacement = function (matchedText, language) {
      return ("" + String(matchedText) + "");
    };
    var contentArray = Array.prototype.slice.call(document.querySelectorAll(selector));
    // multi-line code
    var tripleTickRegex = new RegExp(/^```{1}[\w\W]*?^```$/gim);
    // inline code
    var singleTickRegex = new RegExp(/`[^`]+`/g);
    var codeLanguageRegex = new RegExp(/```{1}.*/);
    contentArray.map(function (i) {
      if (i.hasAttribute('contenteditable')) {
        if (!i.innerHTML.match(/<code/gi)) {
          if ((i.textContent.match(codeLanguageRegex) !== null) && (i.textContent !== undefined)) {
            // match the code language, so we can
            // support a lot of awesome syntax highlighting
            // this needs a little extra filtering, but cascading is cool
            var codeLanguage = String(i.textContent.match(codeLanguageRegex)).slice(3).split(/(\s+)/)[0].trim();
            if (i.textContent.match(tripleTickRegex)) {
              i.innerHTML = i.innerHTML.replace(tripleTickRegex, replacement("$&", codeLanguage));
          }
        }
      }
    });
  };

  // attach globally
  window.codeFormatter = codeFormatter;

}());
<commit_msg>add back single tick code<commit_after>/*! codeFormatter v0.1.0 by ryanpcmcquen */
//
// Ryan P.C. McQuen | Everett, WA | ryan.q@linux.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version, with the following exception:
// the text of the GPL license may be omitted.
//
// This program is distributed in the hope that it will be useful, but
// without any warranty; without even the implied warranty of
// merchantability or fitness for a particular purpose. Compiling,
// interpreting, executing or merely reading the text of the program
// may result in lapses of consciousness and/or very being, up to and
// including the end of all existence and the Universe as we know it.
// See the GNU General Public License for more details.
//
// You may have received a copy of the GNU General Public License along
// with this program (most likely, a file named COPYING).  If not, see
// <https://www.gnu.org/licenses/>.

/*global window*/
/*jslint browser:true, white:true*/
(function () {

  'use strict';

  var codeFormatter = function (selector) {
    var replacement = function (matchedText, language) {
      return ("<code class='prettyprint lang-" + (language) + "'>" + String(matchedText) + "</code>");
    };
    var contentArray = Array.prototype.slice.call(document.querySelectorAll(selector));
    // multi-line code
    var tripleTickRegex = new RegExp(/^```{1}[\w\W]*?^```$/gim);
    // inline code
    var singleTickRegex = new RegExp(/`[^`]+`/g);
    var codeLanguageRegex = new RegExp(/```{1}.*/);
    contentArray.map(function (i) {
      if (i.hasAttribute('contenteditable')) {
        if (!i.innerHTML.match(/<code/gi)) {
          if ((i.textContent.match(codeLanguageRegex) !== null) && (i.textContent !== undefined)) {
            // match the code language, so we can
            // support a lot of awesome syntax highlighting
            // this needs a little extra filtering, but cascading is cool
            var codeLanguage = String(i.textContent.match(codeLanguageRegex)).slice(3).split(/(\s+)/)[0].trim();
            if (i.textContent.match(tripleTickRegex)) {
              i.innerHTML = i.innerHTML.replace(tripleTickRegex, replacement("$&", codeLanguage));
            }
            if (i.textContent.match(singleTickRegex)) {
              i.innerHTML = i.innerHTML.replace(singleTickRegex, replacement("$&", codeLanguage));
            }
          }
        }
      }
    });
  };

  // attach globally
  window.codeFormatter = codeFormatter;

}());
<|endoftext|>


<commit_before>var data = require("../data.json");

exports.addFriend = function(req, res) {

	var newFriend = {
		"name": req.query.name,
		"description": req.query.description,
		"imageURL":"http://lorempixel.com/400/400/people"
	};
	data["friends"].push(newFriend);
	res.render('add', data);

}<commit_msg>putting it together lab<commit_after>var data = require("../data.json");

exports.addFriend = function(req, res) {

	var newFriend = {
		"name": req.query.name,
		"description": req.query.description,
		"imageURL":"http://lorempixel.com/400/400/people"
	};
	data["friends"].push(newFriend);
	res.render('add', data);

}
<|endoftext|>


<commit_before>/*
 * Serve JSON to our AngularJS client
 */
var crypto = require('crypto');
var cfg = require('../cfg/cfg');
var STATS_SECRET = process.env.STATS_SECRET || require('../cfg/secrets').stats_secret;
var Stats = require('../models/stats');
var Match = require('../models/match');
var Counter = require('../models/counter');
var Session = require('../models/session');
var Player = require('../models/player');
var statsEmitter = require('../emitters').statsEmitter;

module.exports = function(app) {
  // JSON API
  app.get('/api/stats/:id', stats);
  app.get('/api/matches', matches);

  app.post('/api/stats', addStats);
  app.post('/api/stats/gameover', gameOver);
};

// GET

var stats = function(req, res) {
  var id = req.params.id;
  Stats.findById(id, function(err, stats) {
    if (err) {
      console.log(err);
      return res.json(false);
    }
    if (!stats) {
      return res.json(false);
    }

    stats.getPlayerData(function(err, playerdata) {
      if (err) {
        console.log(err);
        return res.json(false);
      }
      res.json({ stats: stats, playerdata: playerdata });
    });

  });
};

var matches = function(req, res) {
  Match.find({}).sort({_id:-1}).limit(10).exec(function(err, matches) {
    if (err) {
      console.log(err);
      return res.json(false);
    }
    if (!matches) {
      return res.json(false);
    }
    res.json({ matches: matches });
  });
};

// POST

var addStats = function(req, res) {
  // For debugging
  console.log(req.body);

  // Control flow:
  // 1. Check header for api version
  if (!req.body.stats || req.headers.sizzlingstats !== 'v0.1') {
    return res.end('false\n');
  }

  // 2. Check header for sessionid, generate session if needed.
  // If sessionid is supplied, validate it.
  // 3. Then insert stats into database.
  var sessionid = req.headers.sessionid;
  var ip = req.connection.remoteAddress;
  var matchId;
  if (!sessionid) {
    // We probably need some more/better information in the hmac
    var date = Date.now();
    var hmac = crypto.createHmac('sha1',STATS_SECRET);
    hmac.update(ip + date);
    sessionid = hmac.digest('hex');

    // Get matchId
    Counter.findOneAndUpdate({ "counter" : "matches" },
                             { $inc: {next:1} },
                             function(err, matchCounter) {
      if (err) {
        console.log(err);
        return res.end('false\n');
      }
      if (!matchCounter) {
        return res.end('false\n');
      }
      matchId = matchCounter.next;
      // res.setHeader('matchurl', cfg.hosturl + 'match/' +matchId);
      // res.setHeader('sessionid', sessionid);

      // 3. Create new session, match, and stats documents
      new Session({
        _id: sessionid,
        matchId: matchId,
        ip: ip,
        timeout: date + cfg.statsSessionTimeout }).save(function(e) {
        if (e) {
          console.log(e);
          return res.end('false\n');
        }

        newMatch = {
          _id: matchId,
          hostname: req.body.stats.hostname,
          bluname: req.body.stats.bluname,
          redname: req.body.stats.redname,
          isLive: true
        };
        new Match(newMatch).save(function(e) {
          if (e) {
            console.log(e);
            return res.end('false\n');
          }

          var stats = req.body.stats;
          stats.round = 0;
          stats._id = matchId;
          stats.isLive = true;
          stats.created = new Date();

          new Stats(stats).save(function(e) {
            if (e) {
              console.log(e);
              return res.end('false\n');
            }
            statsEmitter.emit('newMatch', newMatch);

            res.setHeader('matchurl', cfg.hosturl + 'match/' + matchId + '?ingame');
            res.setHeader('sessionid', sessionid);
            return res.end('true\n');
          }); // End Stats.save()
        }); // End Match.save()
      }); // End Session.save()
    }); // End Counter.findOneAndUpdate()
  } else {
    // Validate sessionid
    Session.findById(sessionid, function(err, session) {
      if (err) {
        console.log(err);
        return res.end('false\n');
      }
      if (!session || ip !== session.ip) return res.end('false\n');

      // The request is validated, now we have to append the new data to the old
      matchId = session.matchId;
      Stats.appendStats(req.body.stats, matchId, function(err) {
        if (err) {
          console.log(err);
          return res.end('false\n');
        }
        res.setHeader('matchurl', cfg.hosturl + 'match/' +matchId);
        res.setHeader('sessionid', sessionid);
        res.end('true\n');
      });

    }); // end Session.findById()
  } // end else
};

var gameOver = function(req, res) {
  // For debugging
  console.log('gameOver headers:', req.headers);

  if (!req.headers.matchduration || req.headers.sizzlingstats !== 'v0.1') {
    return res.end('false\n');
  }

  var sessionId = req.headers.sessionid;
  var matchDuration = parseInt(req.headers.matchduration, 10);
  var ip = req.connection.remoteAddress;

  // Validate sessionid
  Session.findById(sessionId, function(err, session) {
    if (err) {
      console.log(err);
      return res.end('false\n');
    }
    if (!session || ip !== session.ip) return res.end('false\n');

    // The request is validated, now set game over
    var matchId = session.matchId;
    console.log('matchId:', matchId);

    Stats.setGameOver(matchId, matchDuration, function(err) {
      if (err) {
        console.log(err);
        return res.end('false\n');
      }

      Match.setGameOver(session.matchId, null, function(err) {
        if (err) { console.log(err); }
      });

      // If all went well, expire the sessionkey and send HTTP response
      session.expireSessionKey(function(err) {
        if (err) {
          console.log(err);
          return res.end('false\n');
        }
        res.end('true\n');
      });
    });

  }); // end Session.findById()
};
<commit_msg>Log entire depth of POST body, as well as headers.<commit_after>/*
 * Serve JSON to our AngularJS client
 */
var crypto = require('crypto');
var util = require('util');
var cfg = require('../cfg/cfg');
var STATS_SECRET = process.env.STATS_SECRET || require('../cfg/secrets').stats_secret;
var Stats = require('../models/stats');
var Match = require('../models/match');
var Counter = require('../models/counter');
var Session = require('../models/session');
var Player = require('../models/player');
var statsEmitter = require('../emitters').statsEmitter;

module.exports = function(app) {
  // JSON API
  app.get('/api/stats/:id', stats);
  app.get('/api/matches', matches);

  app.post('/api/stats', addStats);
  app.post('/api/stats/gameover', gameOver);
};

// GET

var stats = function(req, res) {
  var id = req.params.id;
  Stats.findById(id, function(err, stats) {
    if (err) {
      console.log(err);
      return res.json(false);
    }
    if (!stats) {
      return res.json(false);
    }

    stats.getPlayerData(function(err, playerdata) {
      if (err) {
        console.log(err);
        return res.json(false);
      }
      res.json({ stats: stats, playerdata: playerdata });
    });

  });
};

var matches = function(req, res) {
  Match.find({}).sort({_id:-1}).limit(10).exec(function(err, matches) {
    if (err) {
      console.log(err);
      return res.json(false);
    }
    if (!matches) {
      return res.json(false);
    }
    res.json({ matches: matches });
  });
};

// POST

var addStats = function(req, res) {
  // For debugging
  console.log('addStats headers:', req.headers);
  console.log(util.inspect(req.body, false, null, true));

  // Control flow:
  // 1. Check header for api version
  if (!req.body.stats || req.headers.sizzlingstats !== 'v0.1') {
    return res.end('false\n');
  }

  // 2. Check header for sessionid, generate session if needed.
  // If sessionid is supplied, validate it.
  // 3. Then insert stats into database.
  var sessionid = req.headers.sessionid;
  var ip = req.connection.remoteAddress;
  var matchId;
  if (!sessionid) {
    // We probably need some more/better information in the hmac
    var date = Date.now();
    var hmac = crypto.createHmac('sha1',STATS_SECRET);
    hmac.update(ip + date);
    sessionid = hmac.digest('hex');

    // Get matchId
    Counter.findOneAndUpdate({ "counter" : "matches" },
                             { $inc: {next:1} },
                             function(err, matchCounter) {
      if (err) {
        console.log(err);
        return res.end('false\n');
      }
      if (!matchCounter) {
        return res.end('false\n');
      }
      matchId = matchCounter.next;
      // res.setHeader('matchurl', cfg.hosturl + 'match/' +matchId);
      // res.setHeader('sessionid', sessionid);

      // 3. Create new session, match, and stats documents
      new Session({
        _id: sessionid,
        matchId: matchId,
        ip: ip,
        timeout: date + cfg.statsSessionTimeout }).save(function(e) {
        if (e) {
          console.log(e);
          return res.end('false\n');
        }

        newMatch = {
          _id: matchId,
          hostname: req.body.stats.hostname,
          bluname: req.body.stats.bluname,
          redname: req.body.stats.redname,
          isLive: true
        };
        new Match(newMatch).save(function(e) {
          if (e) {
            console.log(e);
            return res.end('false\n');
          }

          var stats = req.body.stats;
          stats.round = 0;
          stats._id = matchId;
          stats.isLive = true;
          stats.created = new Date();

          new Stats(stats).save(function(e) {
            if (e) {
              console.log(e);
              return res.end('false\n');
            }
            statsEmitter.emit('newMatch', newMatch);

            res.setHeader('matchurl', cfg.hosturl + 'match/' + matchId + '?ingame');
            res.setHeader('sessionid', sessionid);
            return res.end('true\n');
          }); // End Stats.save()
        }); // End Match.save()
      }); // End Session.save()
    }); // End Counter.findOneAndUpdate()
  } else {
    // Validate sessionid
    Session.findById(sessionid, function(err, session) {
      if (err) {
        console.log(err);
        return res.end('false\n');
      }
      if (!session || ip !== session.ip) return res.end('false\n');

      // The request is validated, now we have to append the new data to the old
      matchId = session.matchId;
      Stats.appendStats(req.body.stats, matchId, function(err) {
        if (err) {
          console.log(err);
          return res.end('false\n');
        }
        res.setHeader('matchurl', cfg.hosturl + 'match/' +matchId);
        res.setHeader('sessionid', sessionid);
        res.end('true\n');
      });

    }); // end Session.findById()
  } // end else
};

var gameOver = function(req, res) {
  // For debugging
  console.log('gameOver headers:', req.headers);

  if (!req.headers.matchduration || req.headers.sizzlingstats !== 'v0.1') {
    return res.end('false\n');
  }

  var sessionId = req.headers.sessionid;
  var matchDuration = parseInt(req.headers.matchduration, 10);
  var ip = req.connection.remoteAddress;

  // Validate sessionid
  Session.findById(sessionId, function(err, session) {
    if (err) {
      console.log(err);
      return res.end('false\n');
    }
    if (!session || ip !== session.ip) return res.end('false\n');

    // The request is validated, now set game over
    var matchId = session.matchId;

    Stats.setGameOver(matchId, matchDuration, function(err) {
      if (err) {
        console.log(err);
        return res.end('false\n');
      }

      Match.setGameOver(session.matchId, null, function(err) {
        if (err) { console.log(err); }
      });

      // If all went well, expire the sessionkey and send HTTP response
      session.expireSessionKey(function(err) {
        if (err) {
          console.log(err);
          return res.end('false\n');
        }
        res.end('true\n');
      });
    });

  }); // end Session.findById()
};
<|endoftext|>