cartodb-4.42/app/models/carto/helpers/user_commons.rb
2024-04-06 05:25:13 +00:00

385 lines
12 KiB
Ruby

require_dependency 'carto/helpers/batch_queries_statement_timeout'
require_dependency 'carto/helpers/billing'
require_dependency 'carto/helpers/google_maps'
require_dependency 'carto/helpers/has_connector_configuration'
require_dependency 'carto/helpers/limits'
require_dependency 'carto/helpers/multifactor_authentication'
require_dependency 'carto/helpers/oauth_services'
require_dependency 'carto/helpers/password'
require_dependency 'carto/helpers/password_rate_limit'
require_dependency 'carto/helpers/urls'
require_dependency 'carto/helpers/varnish_cache_handler'
require_dependency 'carto/gcloud_user_settings'
require_dependency 'carto/helpers/sessions_invalidations'
module Carto::UserCommons
include Carto::BatchQueriesStatementTimeout
include Carto::Billing
include Carto::GoogleMaps
include Carto::HasConnectorConfiguration
include Carto::Limits
include Carto::MultifactorAuthentication
include Carto::OauthServices
include Carto::Password
include Carto::PasswordRateLimit
include Carto::Urls
include Carto::VarnishCacheHandler
include Carto::SessionsInvalidations
STATE_ACTIVE = 'active'.freeze
STATE_LOCKED = 'locked'.freeze
LOGGING_ATTRIBUTES = %i[username admin enabled map_enabled quota_in_bytes
table_quota account_type private_tables_enabled period_end_date map_view_quota
max_layers database_timeout user_timeout upgraded_at map_view_block_price
geocoding_quota dashboard_viewed_at sync_tables_enabled database_host
geocoding_block_price notification organization_id created_at updated_atid
soft_geocoding_limit twitter_datasource_enabled
twitter_datasource_block_price twitter_datasource_block_size twitter_datasource_quota
soft_twitter_datasource_limit private_maps_enabled google_sign_in
max_import_file_size max_import_table_row_count
max_concurrent_import_count last_common_data_update_date
here_isolines_quota here_isolines_block_price soft_here_isolines_limit obs_snapshot_quota
obs_snapshot_block_price soft_obs_snapshot_limit mobile_xamarin mobile_custom_watermark
mobile_offline_maps mobile_gis_extension mobile_max_open_users mobile_max_private_users
obs_general_quota obs_general_block_price soft_obs_general_limit viewer
salesforce_datasource_enabled builder_enabled geocoder_provider isolines_provider
routing_provider engine_enabled mapzen_routing_quota
mapzen_routing_block_price soft_mapzen_routing_limit no_map_logo org_admin
user_render_timeout database_render_timeout frontend_version asset_host
state rate_limit_id public_map_quota regular_api_key_quota
maintenance_mode private_map_quota public_dataset_quota]
# Make sure the following date is after Jan 29, 2015,
# which is the date where a message to accept the Terms and
# conditions and the Privacy policy was included in the Signup page.
# See https://github.com/CartoDB/cartodb-central/commit/3627da19f071c8fdd1604ddc03fb21ab8a6dff9f
FULLSTORY_ENABLED_MIN_DATE = Date.new(2017, 1, 1)
# +--------+---------+------+
# valid_privacy logic | Public | Private | Link |
# +-------------------------+--------+---------+------+
# | private_tables_enabled | T | T | T |
# | !private_tables_enabled | T | F | F |
# +-------------------------+--------+---------+------+
#
def valid_privacy?(privacy)
private_tables_enabled || privacy == Carto::UserTable::PRIVACY_PUBLIC
end
def twitter_configured?
# DatasourcesFactory.config_for takes configuration from organization if user is an organization user
CartoDB::Datasources::DatasourcesFactory.customized_config?(Search::Twitter::DATASOURCE_NAME, self)
end
def oauth_signin?
google_sign_in || github_user_id.present?
end
def created_with_http_authentication?
Carto::UserCreation.http_authentication.find_by_user_id(id).present?
end
def database_public_username
database_schema == CartoDB::DEFAULT_DB_SCHEMA ? CartoDB::PUBLIC_DB_USER : "cartodb_publicuser_#{id}"
end
# Gets the list of OAuth accounts the user has (currently only used for synchronization)
# @return CartoDB::OAuths
def oauths
@oauths ||= CartoDB::OAuths.new(self)
end
def unverified?
(active? || locked?) &&
email_verification_token.present? &&
email_verification_sent_at.present? &&
email_verification_sent_at < 1.hour.ago && !oauth_signin?
end
def remove_logo?
has_organization? ? organization.no_map_logo : no_map_logo
end
def viewable_by?(viewer)
id == viewer.id || organization.try(:admin?, viewer)
end
def editable_by?(user)
id == user.id || user.belongs_to_organization?(organization) && (user.organization_owner? || !organization_admin?)
end
# create the core user_metadata key that is used in redis
def key
"rails:users:#{username}"
end
def timeout_key
"limits:timeout:#{username}"
end
def get_auth_tokens
tokens = [get_auth_token]
if has_organization?
tokens << organization.get_auth_token
tokens += groups.map(&:get_auth_token)
end
tokens
end
def can_change_email?
(!google_sign_in || last_password_change_date.present?) && !Carto::Ldap::Manager.new.configuration_present?
end
def cant_be_deleted_reason
if organization_owner?
"You can't delete your account because you are admin of an organization"
elsif Carto::UserCreation.http_authentication.where(user_id: id).first.present?
"You can't delete your account because you are using HTTP Header Authentication"
end
end
def remaining_quota(db_size = db_size_in_bytes)
return nil unless db_size
quota_in_bytes - db_size
end
def remaining_table_quota
if table_quota.present?
remaining = table_quota - table_count
remaining.negative? ? 0 : remaining
end
end
def organization_user?
organization.present?
end
alias_method :has_organization?, :organization_user?
def organization_owner?
organization_user? && organization.owner_id == id
end
def organization_admin?
organization_user? && (organization_owner? || org_admin)
end
def belongs_to_organization?(org)
organization_user? && organization_id == org&.id
end
def sql_safe_database_schema
database_schema.include?('-') ? "\"#{database_schema}\"" : database_schema
end
def name_or_username
name.present? || last_name.present? ? [name, last_name].select(&:present?).join(' ') : username
end
def mobile_sdk_enabled?
private_apps_enabled? || open_apps_enabled?
end
def private_apps_enabled?
mobile_max_private_users.positive?
end
def open_apps_enabled?
mobile_max_open_users.positive?
end
def builder?
!viewer?
end
def viewer?
viewer
end
def builder_enabled?
if has_organization? && builder_enabled.nil?
organization.builder_enabled
else
!!builder_enabled
end
end
def engine_enabled?
if has_organization? && engine_enabled.nil?
organization.engine_enabled
else
!!engine_enabled
end
end
def new_visualizations_version
builder_enabled? ? 3 : 2
end
def relevant_frontend_version
frontend_version || CartoDB::Application.frontend_version
end
def active?
state == STATE_ACTIVE
end
def locked?
state == STATE_LOCKED
end
def maintenance_mode?
maintenance_mode == true
end
def fullstory_enabled?
Carto::AccountType::FULLSTORY_SUPPORTED_PLANS.include?(account_type) && created_at > FULLSTORY_ENABLED_MIN_DATE
end
def get_database_roles
api_key_roles = api_keys.reject { |k| k.db_role =~ /^publicuser/ }.map(&:db_role)
oauth_app_owner_roles = api_keys.reject { |k| k.effective_ownership_role_name == nil }.map(&:effective_ownership_role_name)
(api_key_roles + oauth_app_owner_roles).uniq
end
def make_token
Carto::Common::EncryptionService.make_token
end
def role_display
viewer ? 'viewer' : 'builder'
end
# TODO: replace .to_hash with .to_h, and monkeypatch Sequel model to respond to :attributes
def logging_attrs
if self.respond_to?(:attributes)
# AR
attrs = attributes.symbolize_keys
else
# Sequel
attrs = to_hash
end
attrs.slice(*LOGGING_ATTRIBUTES)
end
def update_do_subscription(attributes)
return if attributes.nil?
license_srv = Carto::DoLicensingService.new(self.username)
if attributes[:action] == 'rm'
license_srv.remove_from_redis(attributes[:do_dataset][:dataset_id])
elsif attributes[:action] == 'add'
license_srv.add_to_redis(attributes[:do_dataset])
else
message = 'Error updating a DO subscription: unknown action'
log_error(message: message)
raise message
end
end
def do_subscription(dataset_id)
subscriptions = Carto::DoLicensingService.new(username).subscriptions
subscriptions.find { |subscription| subscription['id'] == dataset_id }&.with_indifferent_access
end
def update_gcloud_settings(attributes)
return if attributes.nil?
settings = Carto::GCloudUserSettings.new(self)
settings.update attributes
end
def gcloud_settings
@gcloud_settings ||= Carto::GCloudUserSettings.new(self).read&.with_indifferent_access
end
def do_enabled?
gcloud_settings[:service_account].present?
end
def has_access_to_coverband?
return true unless Rails.env.production?
organization&.name == 'team'
end
def feature_flags
feature_flags_ids = self_feature_flags.pluck(:id) + Carto::FeatureFlag.not_restricted.pluck(:id)
feature_flags_ids += organization.inheritable_feature_flags.pluck(:id) if organization
Carto::FeatureFlag.where(id: feature_flags_ids)
end
def feature_flags_names
feature_flags.pluck(:name)
end
def has_feature_flag?(feature_flag_name)
feature_flags.exists?(name: feature_flag_name)
end
def activate_feature_flag!(feature_flag)
return if Carto::FeatureFlagsUser.exists?(feature_flag: feature_flag, user_id: id)
Carto::FeatureFlagsUser.create!(feature_flag: feature_flag, user_id: id)
end
def update_feature_flags(feature_flag_ids = nil)
return unless feature_flag_ids
self_feature_flags_user.where.not(feature_flag_id: feature_flag_ids).destroy_all
new_feature_flags_ids = feature_flag_ids - self_feature_flags_user.pluck(:feature_flag_id)
new_feature_flags_ids.each do |feature_flag_id|
self_feature_flags_user.find_or_create_by(feature_flag_id: feature_flag_id)
end
end
def remaining_twitter_quota
if active_record_organization.present?
remaining = active_record_organization.remaining_twitter_quota
else
remaining = twitter_datasource_quota - get_twitter_imports_count
end
(remaining > 0 ? remaining : 0)
end
def effective_twitter_total_quota
active_record_organization.present? ? active_record_organization.twitter_datasource_quota : twitter_datasource_quota
end
def effective_twitter_block_price
active_record_organization.present? ? active_record_organization.twitter_datasource_block_price : twitter_datasource_block_price
end
def effective_twitter_datasource_block_size
active_record_organization.present? ? active_record_organization.twitter_datasource_block_size : twitter_datasource_block_size
end
def effective_get_twitter_imports_count
active_record_organization.present? ? active_record_organization.get_twitter_imports_count : get_twitter_imports_count
end
# Should return the number of tweets imported by this user for the specified period of time, as an integer
def get_twitter_imports_count(options = {})
date_to = (options[:to] ? options[:to].to_date : Date.today)
date_from = (options[:from] ? options[:from].to_date : last_billing_cycle)
Carto::SearchTweet.twitter_imports_count(search_tweets, date_from, date_to)
end
alias get_twitter_datasource_calls get_twitter_imports_count
def active_record_organization
if organization.present?
if organization.kind_of?(ActiveRecord::Base)
organization
else
Carto::Organization.find(organization.id)
end
end
end
end