CurrentUser.js

import Identity from './models/communities/Identity';
import ConflictUser from './models/communities/ConflictUser';
import UserUpdate from './models/UserUpdate';
import BanInfo from './models/BanInfo';

import SDK from './sdk';
import { Storage } from './storage';

import "./thrift/exceptions_types";
import { isAValidImage, uploadFile } from './utils';

export default class CurrentUser {
    /**
     * Creates a new CurrentUser instance from the provider parameters.
     *
     * @constructor CurrentUser
     * @param {Object} userMap - Public User parameters
     * @param {string} userMap.id - User ID
     * @param {string} userMap.displayName - User Display name
     * @param {string} [userMap.avatarUrl] - User Avatar URL
     * @param {Object[]} [userMap.identities=[]] - User identities map
     * @param {Object<string, string>} [userMap.publicProperties={}] - User public properties
     * @param {Object<string, string>} [userMap.privateProperties={}] - User private properties
     * * @param {boolean} [userMap.verified=false] - True if user is verified
     */
   constructor(userMap) {
        this.id = userMap.id;
        this.displayName = userMap.displayName;
        this.avatarUrl = userMap.avatarUrl || null;
        this.identities = userMap.identities || [];
        this.publicProperties = userMap.publicProperties || {};
        this.privateProperties = userMap.privateProperties || {};
        this.verified = userMap.verified || false;
        Object.freeze(this);
    }

    /**
     * Requests a bulk change of properties for the current user.
     *
     * @memberof CurrentUser
     * @instance
     * @param {UserUpdate} update - New user details.
     * @return {Promise<boolean>} Promise to indicate if this operation was successful.
     */
    updateDetails(update) {
        let promise = Promise.resolve();

        if (update.avatarFile) {
            if (update.avatarFile.size > SDK._uploadFileSizeLimit) {
                const oneMb = 1024 * 1024;
                return Promise.reject(new Error(
                    `Avatar is too big (${(update.avatarFile.size / oneMb).toFixed(2)}Mb), limit is ${Math.round(SDK._uploadFileSizeLimit / oneMb)}Mb`
                ));
            }

            if (!isAValidImage(update.avatarFile)) {
                return Promise.reject(new Error(
                    `File must be an image. Type ${update.avatarFile.type} is not supported`
                ));
            }

            promise = uploadFile(update.avatarFile, 'USER_AVATAR')
                .then((resource) => {
                    update.avatarUrl = resource.jpg
                        ? resource.jpg
                        : resource[Object.keys(resource).pop()];
                });
        }

        return promise.then(() => {
            return SDK.request('updateUser', update)
                .then((user) => {
                    Storage.updateUser(user);
                    SDK._currentUser = CurrentUser.create(user);

                    return true;
                })
                .catch(() => false);
        });
    }

    /**
     * Returns if current user has any authentication info attached.
     *
     * @memberof CurrentUser
     * @instance
     * @return {bool} true, if user does not have any authentication info attached.
     */
    isAnonymous() {
        return Object.keys(this.identities).length === 0;
    }

    /**
     * Adds Identity for the specified provider.
     *
     * @memberof CurrentUser
     * @instance
     * @param {Identity} identity - AuthIdentity to be added.
     * @return {Promise} Promise successfull if identity added or error in case of ConflictUser or any other issue.
     */
    addIdentity(identity) {
        return SDK.request('addIdentity', identity.getTHIdentity())
            .then((res) => {
                return !!res;
            })
            .catch((err) => {
                if (err &&
                    (err.errorCode === THErrorCode.IdentityAlreadyExists ||
                        err.errorCode === THErrorCode.EMResourceAlreadyExists)) {
                    return SDK.request(
                        'getPrivateUserByIdentity',
                        identity.getTHIdentity()
                    )
                        .then((res) => {
                            throw new ConflictUser(res);
                        })
                        .catch ((err) => { throw err });
                } else {
                    throw err;
                }
            });
    }

    /**
     * Removes Identity for the specified provider.
     *
     * @memberof CurrentUser
     * @instance
     * @param {string} provider - The provider connected to an auth identity on the current user.
     * @return {Promise} Promise resolves when operation finishes.
     */
    removeIdentity(provider) {
        return SDK.request('removeIdentity', { provider })
            .then(() => true);
    }

    /**
     * Refresh user properties.
     *
     * @memberof CurrentUser
     * @instance
     * @return {Promise} Promise resolves when operation finishes.
     */
    refresh() {
        return SDK.request('getPrivateUser', this.id)
            .then((res) => {
                Storage.updateUser(res);
                SDK._banInfo = res.internalPrivateProperties.ban_expiry
                    ? new BanInfo({
                        expiration: res.internalPrivateProperties.ban_expiry,
                        reason: res.internalPrivateProperties.ban_reason
                    })
                    : null;
                SDK._currentUser = CurrentUser.create(res);

                return;
            })
    }

    /**
     * Returns reason and expiration of the ban of the current user.
     *
     * @memberof CurrentUser
     * @instance
     * @return {BanInfo} Ban information
     */
    getBanInfo() {
        const now = parseInt((new Date()).getTime()/1000);

        // Check if expiration time is in the past
        if (SDK._banInfo &&
            SDK._banInfo.expiration &&
            SDK._banInfo.expiration < now) {
            // Clear ban info
            SDK._banInfo = null;
        }

        return SDK._banInfo;
    }

    /**
     * Returns if user is banned or not.
     *
     * @memberof CurrentUser
     * @instance
     * @return {bool} True, if user is banned, otherwise false.
     */
    isBanned() {
        return !!this.getBanInfo();
    }

    /**
     * Create CurrentUser from THPrivateUser
     *
     * @memberof CurrentUser
     * @param {Object} user - THPrivateUser instance
     * @returns {CurrentUser} CurrentUser instance
     * @ignore
     */
   static create(user) {
    return new CurrentUser({
      ...user,
      verified: user.isVerified ||
        user.verified ||
        (user.internalPublicProperties &&
          !!user.internalPublicProperties.verified)
    });
  }
}