Source: backbone-x/source/ext/session.js

/*jshint indent:2, curly:true, eqeqeq:true, immed:true, latedef:true,
newcap:true, noarg:true, regexp:true, undef:true, strict:true, trailing:true,
white:true*/
/*global XT:true, XM:true, Backbone:true, _:true, console:true, setTimeout: true, enyo:true */

(function () {
  "use strict";

  /**
    @class XT.Session
    @name XT.Session
  */
  _.extend(XT.Session, /** @lends XT.Session# */{

    privileges: {},
    relevantPrivileges: [], // those privileges that are needed for an active extension

    /*

    // privilege segments generated by
    var privs = [
    "ViewProjectBudget",
    ...
    "ViewProjectFinancialReport"
    ];

    var objects = [
      {label: "Account", keywords: ["Account"]},
      {label: "Contact", keywords: ["Contact", "Honorific", "Title"]},
      {label: "ToDo", keywords: ["ToDo"]},
      {label: "Opportunity", keywords: ["Opportunit"]},
      {label: "Incident", keywords: ["Incident", "EmailProfiles"]},
      {label: "Project", keywords: ["Project"]},
      {label: "Customer", keywords: ["Customer"]},
      {label: "SalesOrder", keywords: ["SalesOrder"]},
      {label: "Tax", keywords: ["Tax"]},
      {label: "Currency", keywords: ["Currenc"]},
      {label: "Address", keywords: ["Address", "Country", "State"]},
      {label: "Item", keywords: ["ItemMaster"]}
    ];

    var globalMatched = [];
    _.each(objects, function (obj) {
      var allMatched = [];
      _.each(obj.keywords, function (keyword) {
        var matched = _.filter(privs, function (priv) {
          return priv.indexOf(keyword) >= 0;
        });
        allMatched = _.union(allMatched, matched);
        globalMatched = _.union(globalMatched, matched);
      });
      console.log(obj.label + ":", allMatched, ",");
    });
    */


    privilegeSegments: {
      Account: ["MaintainBankAccounts", "MaintainAccountingPeriods", "ViewAccountingPeriods", "MaintainSalesAccount", "ViewSalesAccount", "MaintainChartOfAccounts", "MaintainVendorAccounts", "ViewVendorAccounts", "MaintainAllCRMAccounts", "ViewAllCRMAccounts", "MaintainPersonalCRMAccounts", "ViewPersonalCRMAccounts", "ViewBankAccountsDock", "ViewGLAccountsDock", "ViewMyAccountsDock", "ViewAccountingDesktop"],
      Contact: ["MergeContacts", "MaintainAllContacts", "ViewAllContacts", "MaintainPersonalContacts", "ViewPersonalContacts", "ViewMyContactsDock", "MaintainTitles", "ViewTitles"],
      ToDo: ["ReassignToDoItems", "ViewAllToDoItems", "MaintainAllToDoItems", "MaintainPersonalToDoItems", "ViewPersonalToDoItems"],
      Opportunity: ["MaintainOpportunitySources", "MaintainOpportunityStages", "MaintainOpportunityTypes", "MaintainAllOpportunities", "ViewAllOpportunities", "MaintainPersonalOpportunities", "ViewPersonalOpportunities"],
      Incident: ["MaintainIncidentCategories", "MaintainIncidentPriorities", "MaintainIncidentSeverities", "MaintainIncidentResolutions", "CloseAllIncidents", "ClosePersonalIncidents", "MaintainAllIncidents", "ViewAllIncidents", "MaintainPersonalIncidents", "ViewPersonalIncidents", "ViewPersonalIncidentHistory", "MaintainEmailProfiles"],
      Project: ["MaintainAllProjects", "ViewAllProjects", "MaintainPersonalProjects", "ViewPersonalProjects", "ViewProjectBudget", "ViewProjectFinancialReport"],
      Customer: ["ViewCustomerMasters", "ViewCustomerTypes", "MaintainCustomerTypes", "UpdateCustomerCreditStatus", "ViewCustomerPrices", "MaintainCustomerGroups", "ViewCustomerGroups", "CreateSOForHoldCustomer", "CreateSOForWarnCustomer", "UpdateCustomerCreditStatus", "MaintainCustomerMastersCustomerType", "MaintainCustomerMastersCustomerTypeOnCreate", "MaintainCustomerMasters"],
      Quote: ["MaintainQuotes", "ViewQuotes"],
      SalesOrder: ["MaintainSalesOrders", "ViewSalesOrders", "ShowMarginsOnSalesOrder", "FirmSalesOrder", "ViewSalesOrdersDock", "OverridePrice", "CreateSOForHoldCustomer", "CreateSOForWarnCustomer", "OverrideSODate", "AlterPackDate"],
      Tax: ["MaintainTaxAuthorities", "ViewTaxAuthorities", "MaintainTaxTypes", "ViewTaxTypes", "OverrideTax", "MaintainTaxReconciliations", "ViewTaxReconciliations", "MaintainTaxCodes", "ViewTaxCodes", "ViewTaxZones", "MaintainTaxZones", "ViewTaxClasses", "MaintainTaxClasses", "MaintainTaxAssignments", "ViewTaxAssignments", "MaintainTaxRegistrations", "ViewTaxRegistrations"],
      Currency: ["CreateNewCurrency", "MaintainCurrencies", "MaintainCurrencyRates", "ViewCurrencyRates"],
      Address: ["ViewVendorAddresses", "MaintainVendorAddresses", "MaintainAddresses", "ViewAddresses", "MaintainStates"],
      Item: ["ViewItemMasters", "MaintainItemMasters", "DeleteItemMasters"],
      ItemSite: ["ViewItemSites", "MaintainItemSites", "DeleteItemSites"],
      Inventory: ["MaintainCarriers", "ViewShipping", "ViewLocations", "ViewInventoryAvailability", "CreateAdjustmentTrans", "CreateScrapTrans", "CreateReceiptTrans", "CreateInterWarehouseTrans", "MaintainItemSites", "ViewItemSites", "PostCountSlips", "EnterCountSlips", "DeleteCountTags", "ZeroCountTags", "ViewCountTags", "PostCountTags", "PurgeCountSlips", "PurgeCountTags", "ViewInventoryValue", "RelocateInventory", "ReassignLotSerial", "ViewQOH", "UpdateCycleCountFreq", "UpdateLeadTime", "SummarizeInventoryTransactions", "ThawInventory", "MaintainCostCategories", "ViewCostCategories", "DeleteCountSlips", "PrintBillsOfLading", "ShipOrders", "ReturnStockFromShipping", "IssueStockToShipping", "PurgeShippingRecords", "ViewDestinations", "MaintainDestinations", "EnterShippingInformation", "RecallOrders", "ViewCarriers", "EnterReceipts", "EnterReturns", "UpdateOUTLevels", "UpdateReorderLevels", "MaintainPackingListBatch", "ViewPackingListBatch", "MaintainCharacteristics",
"ViewCharacteristics", "DeleteItemSites", "CreateExpenseTrans", "CreateTransformTrans", "RecallInvoicedShipment", "ViewItemAvailabilityWorkbench", "MaintainTransferOrders", "ViewTransferOrders", "OverrideTODate", "ViewInventoryHistory", "ViewWarehouses", "MaintainWarehouses", "UpdateABCClass", "FreezeInventory", "EnterMiscCounts", "IssueCountTags", "EnterCountTags", "MaintainLocations", "AlterTransactionDates", "MaintainExternalShipping", "MaintainSiteTypes", "ViewSiteTypes", "ReleaseTransferOrders"]
    },
    settings: {},
    schemas: {
      XM: false // false means we have not yet fetched it
    },

    SETTINGS: 0x01,
    PRIVILEGES: 0x02,
    SCHEMA: 0x04,
    LOCALE: 0x08, // no longer used
    PREFERENCES: 0x10,
    ALL: 0x01 | 0x02 | 0x04 | 0x08 | 0x10,

    /**
      Loads session objects for settings, preferences and privileges into local
      memory. Types `XT.session.SETTINGS` or `XT.session.PRIVILEGES` can be passed
      as bitwise operators. If no arguments are passed the default is
      `XT.session.ALL` which will load all session objects.

      @param {Number} Types
      @param {Object} Options
    */
    loadSessionObjects: function (types, options) {
      var that = this,
        privilegesOptions,
        settingsOptions,
        settings,
        schemaOptions,
        preferencesOptions,
        extensionOptions,
        callback,
        schemaCount = 0,
        schemasReturned = 0,
        i;

      if (options && options.success && options.success instanceof Function) {
        callback = options.success;
      } else {
        callback = function () {};
      }

      if (types === undefined) { types = this.ALL; }

      if (types & this.PRIVILEGES) {
        privilegesOptions = options ? _.clone(options) : {};

        // callback
        privilegesOptions.success = function (resp) {
          var privileges, i;

          if (that.getPrivileges().attributes) {
            // add incoming data to already loaded privilege
            privileges = that.getPrivileges();

          } else {
            // create privilege as a new model
            privileges = new Backbone.Model();
            privileges.get = function (attr) {
              // Sometimes the answer is already known...
              if (_.isBoolean(attr)) { return attr; }
              return Backbone.Model.prototype.get.call(this, attr);
            };
          }

          // Loop through the response and set a privilege for each found.
          for (i = 0; i < resp.length; i++) {
            privileges.set(resp[i].privilege, resp[i].isGranted);
          }

          // Attach the privileges to the session object.
          that.setPrivileges(privileges);
          callback();
        };

        XM.ModelMixin.dispatch('XT.Session', 'privileges', null, privilegesOptions);

      }

      if (types & this.SETTINGS) {
        settingsOptions = options ? _.clone(options) : {};

        // callback
        settingsOptions.success = function (resp) {
          settings = new Backbone.Model(resp);

          // Attach the settings to the session object
          that.setSettings(settings);

          callback();
        };

        XM.ModelMixin.dispatch('XT.Session', 'settings', null, settingsOptions);
      }

      if (types & this.SCHEMA) {
        schemaOptions = options ? _.clone(options) : {};

        // callback
        schemaOptions.success = function (resp, options) {
          var schema,
            prop,
            Klass,
            relations,
            rel,
            obj,
            proto,
            i;

          if (that.getSchemas()[options.schemaName].attributes) {
            // add incoming data to already loaded schema attributes
            schema = that.getSchemas()[options.schemaName];
            schema.set(resp);

          } else {
            // create schema as a new model
            schema = new Backbone.Model(resp);
            that.setSchema(options.schemaName, schema);
          }
          schemasReturned++;

          if (schemasReturned === schemaCount) {
            _.each(that.getSchemas(), function (schema, schemaName) {
              // Set relations
              for (var prop in schema.attributes) {
                if (schema.attributes.hasOwnProperty(prop)) {
                  Klass = XM.Model.getObjectByName(schemaName + '.' + prop);
                  if (Klass) {
                    proto = Klass.prototype;
                    obj = schema.attributes[prop];
                    relations = obj.relations || [];
                    if (relations.length) {
                      proto.relations = [];
                      for (i = 0; i < relations.length; i++) {
                        rel = relations[i];
                        if (rel.type === "Backbone.HasOne") {
                          rel.type = Backbone.HasOne;
                        } else if (rel.type === "Backbone.HasMany") {
                          rel.type = Backbone.HasMany;
                        } else {
                          continue;
                        }
                        proto.relations.push(rel);
                      }
                    }

                    proto.idAttribute = obj.idAttribute;
                    proto.lockable = obj.lockable;
                    if (obj.privileges) {
                      // don't overwrite a privilege with undefined if it's
                      // already defined in the model, e.g. XM.Settings
                      proto.privileges = obj.privileges;
                    }
                    proto.requiredAttributes = obj.requiredAttributes;
                  }
                }
              }
            });
            callback();
          }
        };

        schemaOptions.error = function () {
          console.log("schema error", arguments);
        };

        _.each(this.schemas, function (value, schemaName) {
          // get schema for instance DB models
          schemaOptions.schemaName = schemaName;
          XM.ModelMixin.dispatch('XT.Session', 'schema', schemaName.toLowerCase(), schemaOptions);
          schemaCount++;
        });
      }

      if (types & this.PREFERENCES) {
        preferencesOptions = options ? _.clone(options) : {};

        // callback
        preferencesOptions.success = function (resp) {
          var preferences = new XM.UserPreference(resp);
          that.setPreferences(preferences);
          callback();
        };

        XM.ModelMixin.dispatch('XT.Session', 'preferences', null, preferencesOptions);
      }

      return true;
    },

    getPreferences: function () {
      return this.preferences;
    },

    getSchemas: function () {
      return this.schemas;
    },

    getSettings: function () {
      return this.settings;
    },

    getPrivileges: function () {
      return this.privileges;
    },

    setPreferences: function (value) {
      this.preferences = value;
      return this;
    },

    setSchema: function (schemaName, value) {
      this.schemas[schemaName] = value;
      return this;
    },

    setSettings: function (value) {
      this.settings = value;
      return this;
    },

    setPrivileges: function (value) {
      this.privileges = value;
      return this;
    },

    /**
      Each extension has a set of privileges that it cares about. The extension will load those
      privileges here into the session object with then name of the module that the privilege
      should be associated with. The module name will frequently be the extension name, but some
      extensions do not have their own modules.

      @param {String} module
      @param {Array} privArray
    */
    addRelevantPrivileges: function (module, privArray) {
      var privMap = _.map(privArray, function (priv) {return {module: module, privilege: priv}; });
      this.relevantPrivileges = _.union(this.relevantPrivileges, privMap);
    },

    // ..........................................................
    // CLASS CONSTANTS
    //

    DB_BOOLEAN: 'B',
    DB_STRING: 'S',
    DB_COMPOUND: 'C',
    DB_DATE: 'D',
    DB_NUMBER: 'N',
    DB_ARRAY: 'A',
    DB_BYTEA: 'U',
    DB_UNKNOWN: 'X'

  });

}());