CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/dashboard/data/user-model.js

Summary

Maintainability
F
4 days
Test Coverage
const _ = require('underscore');
const Backbone = require('backbone');
const UserUrlModel = require('dashboard/data/user-url-model');

const UserModel = Backbone.Model.extend({
  urlRoot: '/api/v1/users',

  defaults: {
    avatar_url: 'http://cartodb.s3.amazonaws.com/static/public_dashboard_default_avatar.png',
    username: ''
  },

  initialize: function (attrs, opts) {
    attrs = attrs || {};
    opts = opts || {};
    this.tables = [];
    // Removing avatar_url attribute if it comes as null
    // Due to a Backbone Model constructor uses _.extends
    // instead of _.defaults
    if (this.get('avatar_url') === null) {
      this.set('avatar_url', this.defaults.avatar_url);
    }

    this.email = (typeof attrs.email !== 'undefined') ? attrs.email : '';

    if (opts.groups) {
      this.setGroups(opts.groups);
    }

    if (opts.organization) {
      this.setOrganization(opts.organization);
    }
  },

  setGroups: function (groups) {
    this.groups = groups;
  },

  setOrganization: function (organization) {
    this.organization = organization;

    if (this.groups) {
      this.groups.organization = organization;
    }
  },

  isInsideOrg: function () {
    if (this.organization) {
      return this.organization.id !== false || this.isOrgOwner();
    }
    return false;
  },

  isAuthUsernamePasswordEnabled: function () {
    if (this.organization) {
      return this.organization.get('auth_username_password_enabled');
    }
    return false;
  },

  isOrgOwner: function () {
    if (this.organization) {
      return this.organization.owner.get('id') === this.get('id');
    }
    return false;
  },

  isOrgAdmin: function () {
    if (this.organization) {
      return this.organization.isOrgAdmin(this);
    }
    return false;
  },

  isViewer: function () {
    return this.get('viewer') === true;
  },

  isBuilder: function () {
    return !this.isViewer();
  },

  role: function () {
    return this.get('role_display');
  },

  isDOEnabled: function () {
    return this.get('do_enabled');
  },

  isEnterprise: function () {
    return this.get('is_enterprise');
  },

  isIndividualUser: function () {
    const proUsers = ['Individual', 'Annual Individual'];
    return proUsers.indexOf(this.get('account_type')) > -1;
  },

  isFree2020User: function () {
    return this.get('account_type').toLowerCase().indexOf('free 2020') !== -1;
  },

  nameOrUsername: function () {
    return this.fullName() || this.get('username');
  },

  fullName: function () {
    var name = this.get('name') || '';
    var lastName = this.get('last_name') || '';
    if (name || lastName) {
      return name + (name && lastName ? ' ' : '') + lastName;
    }
    return '';
  },

  renderData: function (currentUser) {
    var name = this.get('username');

    if (currentUser && currentUser.id === this.id) {
      name = _t('You');
    }

    return {
      username: name,
      avatar_url: this.get('avatar_url')
    };
  },

  hasCreateDatasetsFeature: function () {
    return this.isBuilder();
  },

  canCreateDatasets: function () {
    if (!this.get('remaining_byte_quota') || this.get('remaining_byte_quota') <= 0) {
      return false;
    }

    return this.hasCreateDatasetsFeature();
  },

  hasCreateMapsFeature: function () {
    return this.isBuilder();
  },

  canAddLayerTo: function (map) {
    if (!map || !map.layers || !map.layers.getDataLayers) {
      throw new Error('Map model is not defined or wrong');
    }
    var dataLayers = map.layers.getDataLayers();
    return dataLayers.length < this.getMaxLayers();
  },

  getMaxLayers: function () {
    return (this.get('limits') && this.get('limits').max_layers) || 5;
  },

  hasPublicMapsLimits: function () {
    const userWithLimits = this.isIndividualUser() || this.isFree2020User();
    return userWithLimits && !this.hasUnlimitedPublicMaps();
  },

  hasRemainingPublicMaps: function () {
    if (this.hasPublicMapsLimits()) {
      return this.get('public_map_quota') > this.getTotalPublicMapsCount();
    }
    return true;
  },

  hasUnlimitedPublicMaps: function () {
    return this.get('public_map_quota') === null;
  },

  getTotalPublicMapsCount: function () {
    var totalPublicPrivacyMapsCount = this.get('public_privacy_map_count') || 0;
    var totalPasswordPrivacyMapsCount = this.get('password_privacy_map_count') || 0;
    var totalLinkPrivacyMapsCount = this.get('link_privacy_map_count') || 0;

    return totalPublicPrivacyMapsCount + totalPasswordPrivacyMapsCount + totalLinkPrivacyMapsCount;
  },

  hasPrivateMapsLimits: function () {
    const userWithLimits = this.isFree2020User();
    return userWithLimits && !this.hasUnlimitedPrivateMaps();
  },

  hasRemainingPrivateMaps: function () {
    if (this.hasPrivateMapsLimits()) {
      return this.get('private_map_quota') > this.getTotalPrivateMapsCount();
    }
    return true;
  },

  hasUnlimitedPrivateMaps: function () {
    return this.get('private_map_quota') === null;
  },

  getTotalPrivateMapsCount: function () {
    return this.get('private_privacy_map_count');
  },

  getMaxConcurrentImports: function () {
    return (this.get('limits') && this.get('limits').concurrent_imports) || 1;
  },

  featureEnabled: function (name) {
    var featureFlags = this.get('feature_flags');

    if (!featureFlags || featureFlags.length === 0 || !name) {
      return false;
    }

    return _.contains(featureFlags, name);
  },

  isCloseToLimits: function () {
    var quota = this.get('quota_in_bytes');
    var remainingQuota = this.get('remaining_byte_quota');

    return ((remainingQuota * 100) / quota) < 20;
  },

  getOrganizationName: function () {
    return this.isInsideOrg() ? this.organization.get('name') : '';
  },

  getOrgName: function () {
    return this.isInsideOrg() ? this.organization.get('name') : '';
  },

  getMaxLayersPerMap: function () {
    return this.get('max_layers') || 4;
  },

  canStartTrial: function () {
    return !this.isInsideOrg() && this.get('account_type') === 'FREE' && this.get('table_count') > 0;
  },

  canCreatePrivateDatasets: function () {
    var actions = this.get('actions');
    return actions && actions.private_tables;
  },

  canCreateTwitterDataset: function () {
    return this.hasOwnTwitterCredentials();
  },

  canSelectPremiumOptions: function (visModel) {
    return this.get('actions')[ visModel.isVisualization() ? 'private_maps' : 'private_tables' ];
  },

  hasOwnTwitterCredentials: function () {
    var twitter = this.get('twitter');
    return (twitter && twitter.customized_config) || false;
  },

  equals: function (otherUser) {
    if (otherUser.get) {
      return this.get('id') === otherUser.get('id');
    }
  },

  viewUrl: function () {
    return new UserUrlModel({
      base_url: this.get('base_url'),
      is_org_admin: this.isOrgAdmin()
    });
  },

  upgradeContactEmail: function () {
    if (this.isInsideOrg()) {
      if (this.isOrgOwner()) {
        return 'enterprise-support@carto.com';
      } else {
        return this.organization.owner.get('email');
      }
    } else {
      return 'support@carto.com';
    }
  },

  needsPasswordConfirmation: function () {
    return this.get('needs_password_confirmation');
  },

  usedQuotaPercentage: function () {
    return (this.get('db_size_in_bytes') * 100) / this.organization.get('available_quota_for_user');
  },

  assignedQuotaInRoundedMb: function () {
    return Math.floor(this.get('quota_in_bytes') / 1024 / 1024).toFixed(0);
  },

  assignedQuotaPercentage: function () {
    return (this.get('quota_in_bytes') * 100) / this.organization.get('available_quota_for_user');
  },

  getGoogleApiKey: function () {
    return this.get('google_maps_private_key');
  },

  hasGoogleMaps: function () {
    return !!this.getGoogleApiKey();
  },

  showGoogleApiKeys: function () {
    return this.hasGoogleMaps() && (!this.isInsideOrg() || this.isOrgOwner());
  },

  getSchema: function () {
    return this.isInsideOrg() ? this.get('username') : 'public';
  },

  getAuthToken: function () {
    return btoa(`${this.get('username')}:${this.get('api_key')}`);
  },

  getModelType: () => 'user',

  isActionEnabled: function (action) {
    return this.get('actions') && this.get('actions')[action];
  },

  hasAccountType: function (accountType) {
    return this.get('account_type') === accountType;
  },

  // Public sharing
  hasPublicMapSharingDisabled: function () {
    return this.get('public_map_quota') === 0;
  },

  hasPublicDatasetSharingDisabled: function () {
    return this.get('public_dataset_quota') === 0;
  }
});

module.exports = UserModel;