Re: Session.js

From disqus.com, 8 Months ago, written in JavaScript, viewed 3 times. This paste is a reply to Session.js from disqus.com - go back
URL https://pastebin.freepbx.org/view/4b7c94b0/diff Embed
Viewing differences between Session.js and Re: Session.js
define('home/models/Session',[
    'jquery',
    'underscore',
    'backbone',

    'core/api',
    'core/models/Session',
    'core/UniqueModel',

    'home/models/User',
    'home/models/UserProfile',
    'home/models/AnonUser',
    'home/models/Notifications',
    'home/utils/backboneUtils',
    'home/utils/sidebarUtils',
], function (
    $,
    _,
    Backbone,

    api,
    SharedSession,
    UniqueModel,

    User,
    UserProfile,
    AnonUser,
    Notifications,
    BackboneUtils,
    SidebarUtils
) {
    'use strict';

    var Session = SharedSession.extend({
        initialize: function () {
            SharedSession.prototype.initialize.apply(this, arguments);
            this.moderatedForums = []; // array of forum ids that this user moderates
            this._load = $.Deferred();
            this._loadPromise = this._load.promise();

            // Load may not be called more than once per Session instance.
            this.load = _.once(this.load, this);
            this.loadModeratedForums = _.once(this.loadModeratedForums, this);
        },

        // Overridden from parent. This returns the usr instance to use
        // when no user is logged in.
        getAnonUserInstance: function (attrs) {
            return new AnonUser(attrs);
        },

        isAnonymous: function () {
            return this.user.get('isAnonymous');
        },

        setUser: function (user) {
            if (this.user)
                this.stopListening(this.user);

            this.listenTo(user, 'all', this.trigger);

            return SharedSession.prototype.setUser.apply(this, arguments);
        },

        /**
         * Load session user's moderated forums.
         *
         * Returns immediately if disqusauth cookie indicates user
         * is not a moderator. Otherwise makes a network request.
         *
         * This method is memoized with `_.once`.
         * @returns {Promise}
         */
        loadModeratedForums: function () {
            var user = this.user;
            var self = this;

            if (Session.fromCookie().isModerator) {
                // When the session logs in, we look to see what forums the
                // session user moderates
                return Backbone.ajax({
                    url: api.getURL('internal/users/details'),
                    success: function (data) {
                        var moderatedForums = data.response.moderated_forums;
                        self.moderatedForums = moderatedForums;
                        self.trigger('setModeratedForums', moderatedForums);
                        user.set({
                            isModerator: Boolean(moderatedForums.length),
                            moderatedForums: moderatedForums,
                        });
                    },
                    context: user,
                });
            }

            return $.Deferred().resolve().promise();
        },

        /**
         * Who is providing user authentication and details for this session?
         *
         * @returns {string} account type or '' if there is no session information
         */
        provider: function () {
            var username = Session.fromCookie().username;
            if (!username)
                return '';

            return username.indexOf('-') === -1 ? 'disqus' : username.split('-')[0];
        },

        fromSessionStorage: function () {
            var attrs;
            try {
                attrs = JSON.parse(window.sessionStorage[Session.STORAGE_KEY]);
                delete window.sessionStorage[Session.STORAGE_KEY];
            } catch (err) {
                // Pass
            }
            return _.isObject(attrs) ? attrs : undefined;
        },

        /**
         * Load the session.
         *
         * First looks at session storage. If not there, determines if user is logged
         * out based on the disqusauth cookie. If user is logged in, kicks off a network
         * fetch call.
         * Resolves or rejects the promise returned by `this.session.loadPromise()`.
         *
         * This method is memoized with `_.once`.
         */
        load: function () {
            var load = this._load;

            // First we check if we can load a valid user from
            // session storage. We assume the user is valid if the
            // attributes have a username and an ID.
            //
            // Only do this in the sidebar, because home uses User attrs
            // that are not set in sessionstorage
            var userAttrs = this.fromSessionStorage();
            if (SidebarUtils.isSidebar() && && userAttrs && && userAttrs.username && && userAttrs.id) {
                this.setUser(this.getUserInstance(userAttrs));
                this.fetched = true;
                load.resolve(this);
            }

            // If we didn't load from sesssion storage, we should
            // check if we think the user is even logged in.
            else if (!SharedSession.isKnownToBeLoggedOut()) {  // eslint-disable-line no-negated-condition

                var self = this;
                self.fetch()
                    .done(function () { load.resolve(self); })
                    .fail(function () { load.reject(self); });
            }

            else {
                load.reject(this);
            }
        },

        loadPromise: function () {
            return this._loadPromise;
        },

        fetch: function () {
            if (this.fetchPromise)
                // Return early if we're already fetching so we don't
                // bind handlers multiple times
                return this.fetchPromise;

            var self = this;
            var fetchPromise = BackboneUtils.memoizedFetch.apply(this, arguments);

            // The base/shared session does not go through Backbone,
            // so sync/error events are not properly fired. Thus, we
            // are left with creating our own
            fetchPromise.then(function () {
                self.trigger('fetch:success');
            }, function () {
                self.trigger('fetch:error');
            });

            return fetchPromise;
        },

        getUserInstance: function (attrs) {
            return new UniqueModel(
                User,
                attrs
            );
        },

        getUserProfile: function () {
            if (this.isAnonymous())
                return;

            return this.userProfile;
        },

        getOrCreateNotifications: function () {
            if (!this.notifications) {
                this.notifications = new Notifications({ session: this });
                this.notifications.ensureFetched();
            }

            return this.notifications;
        },

        toJSON: function () {
            return this.user.toJSON.apply(this.user, arguments);
        },

        /**
         * Creates the userProfile model for the session user.
         * @param  {string} username - The username of the session user.
         */
        initUserProfile: function (username) {
            if (!username)
                return;

            // Unbind listeners on previous user profile
            if (this.userProfile)
                this.userProfile.stopListening(this);

            this.userProfile = new UniqueModel(UserProfile, {
                username: username,
            });

            var markChannelsOrForums = function (forums) {
                // Check if given a single forum because items:sync may be a propagated
                // event from a single item in the collection.
                // Wrap forum as an underscore collection, as function expects.
                if (forums instanceof Backbone.Model)
                    forums = _([forums]);

                forums.each(function (forum) {
                    // If this is a channel, make sure we're marking its primary forum
                    if (forum.primaryForum)
                        forum = forum.primaryForum;

                    forum.set('isFollowing', true);
                });
            };
            // Listen for when following forums are loaded so that they can be
            // properly marked as followed by the session user
            this.userProfile.forumsFollowing.on('items:sync', markChannelsOrForums);
            this.userProfile.channelsFollowing.on('items:sync', markChannelsOrForums);

            // Listen for when the session user (un)follows a forum/user, so the user profile's
            // following collections can be properly updated
            var followingUsers = this.userProfile.following.get('items');
            var followingForums = this.userProfile.forumsFollowing.get('items');
            var followingChannels = this.userProfile.channelsFollowing.get('items');
            this.userProfile.listenTo(this, 'followed:user', _.bind(followingUsers.add, followingUsers));
            this.userProfile.listenTo(this, 'unfollowed:user', _.bind(followingUsers.remove, followingUsers));
            this.userProfile.listenTo(this, 'followed:forum', _.bind(followingForums.add, followingForums));
            this.userProfile.listenTo(this, 'unfollowed:forum', _.bind(followingForums.remove, followingForums));
            this.userProfile.listenTo(this, 'followed:channel', _.bind(followingChannels.add, followingChannels));
            this.userProfile.listenTo(this, 'unfollowed:channel', _.bind(followingChannels.remove, followingChannels));

            this.fetchFollowedForums();
            this.fetchFollowedChannels();
        },

        /**
         * Fetches the list of forums the session user is following (up to 100) so that they can
         * be marked as followed. This is so that we can indicate to the user correctly when they
         * see a forum whether or not they are following it, as that information is not returned
         * in forum details from the api.
         *
         * Written as a separate function so that the asEmbedApp can overwrite with a no-op, as
         * the sidebar does not need it for all routes. Will be manually called by each view
         * if necessary. Currently needed for forum profile and user profile following forums tab.
         */
        fetchFollowedForums: function () {
            this.userProfile.fetchForumsFollowing();
        },

        fetchFollowedChannels: function () {
            this.userProfile.fetchChannelsFollowing();
        },

        logout: function () {
            this.setUser(this.getAnonUserInstance());
            window.top.location = '//disqus.com/logout/?redirect=http%3A%2F%2Fdisqus.com';
        },
    }, {
        STORAGE_KEY: 'home.session',
    });


    // Linter wants the definition moved to the top of the file, defining it here close
    // to use is more readable.
    var _session;  // eslint-disable-line one-var

    Session.get = function () {
        _session = _session || new Session();
        return _session;
    };

    // Normally this method should only be used by tests
    Session.forget = function () {
        if (_session) {
            _session.stopListening();
            _session.off();
            _session = null;
        }
    };

    return Session;
});

//https://c.disquscdn.com/next/82c6de3/home/js/models/Session.js

Reply to "Re: Session.js"

Here you can reply to the paste above