meteor-feature-requests icon indicating copy to clipboard operation
meteor-feature-requests copied to clipboard

Allow multiple AccountsClient from same server and have namespaced localStorage

Open crapthings opened this issue 5 years ago • 3 comments

https://github.com/crapthings/meteor-multiple-accounts-sandbox

this is a demo i've made

https://streamable.com/cnkj4

demo repo

https://github.com/crapthings/meteor-multiple-accounts-sandbox

issue

with 1.8.2 account-base, when we login account, the localStorage only save rootUrl based suffix to key, this cause we can only login 1 user from same rootUrl.

solution (hacky)

https://github.com/crapthings/meteor-multiple-accounts-sandbox/blob/master/mantra-sample-blog-app/packages/accounts-base/accounts_client.js#L17

https://github.com/crapthings/meteor-multiple-accounts-sandbox/blob/master/mantra-sample-blog-app/packages/accounts-base/accounts_client.js#L494

https://github.com/crapthings/meteor-multiple-accounts-sandbox/blob/master/mantra-sample-blog-app/packages/accounts-base/accounts_common.js#L16

after pass new option we can login multiple accounts from same rootUrl.

but the usage about localStorage is still the issue

its better to pass a namespace to any Meteor._localstorage.setItem('key', 'value', 'namespace')

so we can restore state after switch account by namesplaced _localstorage

crapthings avatar Dec 20 '19 08:12 crapthings

localStorage package

https://github.com/meteor/meteor/blob/982181fff86e09a75f1d2681a78b9d784e666f4f/packages/localstorage/localstorage.js#L51

turn into something like this?

https://github.com/crapthings/meteor-multiple-accounts-sandbox/blob/master/mantra-sample-blog-app/packages/localstorage/localstorage.js#L37

// Meteor._localStorage is not an ideal name, but we can change it later.

// Let's test to make sure that localStorage actually works. For example, in
// Safari with private browsing on, window.localStorage exists but actually
// trying to use it throws.
// Accessing window.localStorage can also immediately throw an error in IE (#1291).

var hasOwn = Object.prototype.hasOwnProperty;
var key = '_localstorage_test_' + Random.id();
var retrieved;
var storage;

try {
  storage = global.localStorage;

  if (storage) {
    storage.setItem(key, key);
    retrieved = storage.getItem(key);
    storage.removeItem(key);
  }
} catch (ignored) {}

if (key === retrieved) {
  if (Meteor.isServer) {
    Meteor._localStorage = storage;
  } else {
    // Some browsers (e.g. IE11) don't properly handle attempts to change
    // window.localStorage methods. By using proxy methods to expose
    // window.localStorage functionality, developers can change the
    // behavior of Meteor._localStorage methods without breaking
    // window.localStorage.
    ["getItem",
     "setItem",
     "removeItem",
    ].forEach(function (name) {
      this[name] = function () {
        if (name === "getItem" || name === "removeItem") {
          const arg = arguments
          const namespace = arg[1]
          const key = arg[0]
          if (namespace) {
            arg[0] = key + ':' + namespace
          }
          return storage[name].apply(storage, arg);
        } else if (name === "setItem") {
          const arg = arguments
          const namespace = arg[2]
          const key = arg[0]
          if (namespace) {
            arg[0] = key + ':' + namespace
          }
          return storage[name].apply(storage, arg);
        }
      };
    }, Meteor._localStorage = {});
  }
}

if (! Meteor._localStorage) {
  if (Meteor.isClient) {
    Meteor._debug(
      "You are running a browser with no localStorage or userData "
        + "support. Logging in from one tab will not cause another "
        + "tab to be logged in.");
  }

  Meteor._localStorage = Object.create({
    setItem: function (key, val, namespace) {
      if (namespace) {
        this[namespace + ':' + key] = val;
      } else {
        this[key] = val;
      }
    },

    removeItem: function (key, namespace) {
      if (namespace) {
        delete this[namespace + ':' + key];
      } else {
        delete this[key];
      }
    },

    getItem: function (key, namespace) {
      if (namespace) {
        const _key = namespace + ':' + key;
        return hasOwn.call(this, _key) ? this[_key] : null;
      } else {
        return hasOwn.call(this, key) ? this[key] : null;
      }
    }
  });
}
Meteor._localStorage.setItem('color', 'red', 'u0')
  Meteor._localStorage.setItem('color', 'blue', 'u1')
  Meteor._localStorage.setItem('color', 'green', 'u2')
  Meteor._localStorage.setItem('color', 'purple', 'u3')

after use named localStorage

image

crapthings avatar Dec 20 '19 08:12 crapthings

So to boil this down, the main reason behind this request is to allow user to be logged into multiple accounts at the same time and to switch between them?

StorytellerCZ avatar Mar 29 '21 12:03 StorytellerCZ

Or to have multiple DDP connections to multiple servers.

mitar avatar Mar 29 '21 16:03 mitar