API Docs for: 0.25.0
Show:

File: addon/services/current-user.js

import Ember from 'ember';
import { task } from 'ember-concurrency';
import config from 'ember-get-config';
/**
 * @module ember-osf
 * @submodule services
 */

/**
 * Access information about the currently logged in user
 *
 * @class current-user
 * @extends Ember.Service
 */
export default Ember.Service.extend({
    store: Ember.inject.service(),
    session: Ember.inject.service(),
    features: Ember.inject.service(),
    cookies: Ember.inject.service(),

    waffleLoaded: false,
    csrfCookie: config.OSF.cookies.csrf,
    apiHeaders: config.OSF.apiHeaders,

    init() {
        this._super(...arguments);
        this.get('setWaffle').perform();

        const session = this.get('session');

        session.on('authenticationSucceeded', this, () => this.get('setWaffle').perform());
        session.on('invalidationSucceeded', this, () => this.get('setWaffle').perform());
    },

    setWaffle: task(function* () {
        const url = `${config.OSF.apiUrl}/v2/_waffle/`;
        const { data } = yield this.authenticatedAJAX({
            url,
            method: 'GET',
        });
        for (const flag of data) {
            const { name, active } = flag.attributes;
            if (active) {
                this.get('features').enable(name);
            } else {
                this.get('features').disable(name);
            }
        }
        this.set('waffleLoaded', true);
    }).restartable(),

    getWaffle: task(function* (flag) {
        const setWaffle = this.get('setWaffle');

        if (setWaffle.isRunning) {
            yield setWaffle.last;
        } else if (!this.get('waffleLoaded')) {
            yield setWaffle.perform();
        }
        return this.get('features').isEnabled(flag);
    }),

    /**
     * If logged in, return the ID of the current user, else return null.
     *
     * @property currentUserId
     * @type {String|null}
     */
    currentUserId: Ember.computed('session.data.authenticated', function() {
        const session = this.get('session');
        if (session.get('isAuthenticated')) {
            return session.get('data.authenticated.id');
        } else {
            return null;
        }
    }),

    /**
     * Performs an AJAX request with any additional authorization config as needed for the configured authorization type.
     * Allows manual AJAX requests to be authorization-agnostic when using this addon.
     *
     * Primarily used to set XHR flags on manual AJAX requests, for cookie based authorization.
     * @method authenticatedAJAX
     * @param {Object} options
     * @param {Boolean} addApiHeaders
     * @return {Promise}
     */
    authenticatedAJAX(options, addApiHeaders = true) {
        const opts = Ember.assign({}, options);

        if (config.authorizationType === 'cookie') {
            opts.xhrFields = Ember.assign({
                    withCredentials: true
                }, opts.xhrFields || {});
        }

        if (addApiHeaders) {
            opts.headers = Ember.assign({}, this.ajaxHeaders(), opts.headers || {});
        }

        return Ember.$.ajax(opts);
    },

    /**
     * @method authorizeXHR
     * @param  {XMLHttpRequest} xhr
     * @param  {Boolean} addApiHeaders
     */
    authorizeXHR(xhr, addApiHeaders) {
        if (addApiHeaders) {
            Object.entries(this.ajaxHeaders()).forEach(([key, value]) => {
                  xhr.setRequestHeader(key, value);
            });
        }
        xhr.withCredentials = true;
    },
    /**
     * Return headers that should be included with every AJAX request to the API
     * @method ajaxHeaders
     */
    ajaxHeaders() {
        const headers = Ember.assign({}, this.apiHeaders);
        const csrfCookie = this.csrfCookie;
        const cookies = Ember.get(this, 'cookies');
        const csrfToken = cookies.read(csrfCookie);

        if (csrfToken) {
            headers['X-CSRFToken'] = csrfToken;
        }

        return headers;
    },

    /**
     * Fetch information about the currently logged in user. If no user is logged in, this method returns a rejected promise.
     * @method load
     * @return {Promise}
     */
    load() {
        return new Ember.RSVP.Promise((resolve, reject) => {
            var currentUserId = this.get('currentUserId');
            if (currentUserId) {
                var currentUser = this.get('store').peekRecord('user', currentUserId);
                if (currentUser) {
                    resolve(currentUser);
                } else {
                    this.get('store').findRecord('user', currentUserId).then((user) => resolve(user), reject);
                }
            } else {
                reject();
            }
        });
    },

    /**
     * Return an observable promise proxy for the currently logged in user. If no user is logged in, resolves to null.
     *
     * @property user
     * @return Promise proxy object that resolves to a user or null
     */
    user: Ember.computed('currentUserId', function() {
        const ObjectPromiseProxy = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);
        return ObjectPromiseProxy.create({
            promise: this.load().catch(() => null),
        });
    }),

    /**
     * Return a simple hash of the currentUser ID if user is logged in, otherwise return a generated random string.
     * sessionKey can be used to identify the current session or any general purposes.
     * For Elasticsearch requests, sessionKey is used as the "preference" URL parameter to ensure reproducible search results ordering.
     *
     * @property sessionKey
     * @return {String}
     */
    sessionKey: Ember.computed('currentUserId', function() {
        let currentUserId = this.get('currentUserId');
        if (currentUserId) {
            return this.hashCode(currentUserId).toString();
        }
        return Math.random().toString(36).substr(2,10);
    }),

    /**
     * Generate a simple hash (numerical code) from a string.
     * https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery
     *
     * @method hashCode
     * @param  str {String}
     * @return {String}
     */

    hashCode(str) {
        let hash = 0, i, chr;
        if (str.length === 0) return hash;
        for (i = 0; i < str.length; i++) {
            chr   = str.charCodeAt(i);
            hash  = ((hash << 5) - hash) + chr;
            hash |= 0;
        }
        return hash;
    },

});