<commit_before># encoding: UTF-8

require 'active_record'
require_relative 'user_service'
require_relative 'user_db_service'
require_relative 'synchronization_oauth'
require_relative '../../helpers/data_services_metrics_helper'
require_dependency 'carto/helpers/auth_token_generator'
require_dependency 'carto/helpers/has_connector_configuration'
require_dependency 'carto/helpers/batch_queries_statement_timeout'

# TODO: This probably has to be moved as the service of the proper User Model
class Carto::User < ActiveRecord::Base
  extend Forwardable
  include DataServicesMetricsHelper
  include Carto::AuthTokenGenerator
  include Carto::HasConnectorConfiguration
  include Carto::BatchQueriesStatementTimeout

  MIN_PASSWORD_LENGTH = 6
  MAX_PASSWORD_LENGTH = 64
  GEOCODING_BLOCK_SIZE = 1000
  HERE_ISOLINES_BLOCK_SIZE = 1000
  OBS_SNAPSHOT_BLOCK_SIZE = 1000
  OBS_GENERAL_BLOCK_SIZE = 1000
  MAPZEN_ROUTING_BLOCK_SIZE = 1000

  # INFO: select filter is done for security and performance reasons. Add new columns if needed.
  DEFAULT_SELECT = "users.email, users.username, users.admin, users.organization_id, users.id, users.avatar_url," \
                   "users.api_key, users.database_schema, users.database_name, users.name, users.location," \
                   "users.disqus_shortname, users.account_type, users.twitter_username, users.google_maps_key, " \
                   "users.viewer, users.quota_in_bytes, users.database_host, users.crypted_password, " \
                   "users.builder_enabled, users.private_tables_enabled, users.private_maps_enabled".freeze

  has_many :tables, class_name: Carto::UserTable, inverse_of: :user
  has_many :visualizations, inverse_of: :user
  has_many :maps, inverse_of: :user
  has_many :layers_user
  has_many :layers, through: :layers_user, after_add: Proc.new { |user, layer| layer.set_default_order(user) }

  belongs_to :organization, inverse_of: :users
  has_one :owned_organization, class_name: Carto::Organization, inverse_of: :owner, foreign_key: :owner_id
  has_one :static_notifications, class_name: Carto::UserNotification, inverse_of: :user

  has_many :feature_flags_user, dependent: :destroy, foreign_key: :user_id, inverse_of: :user
  has_many :feature_flags, through: :feature_flags_user
  has_many :assets, inverse_of: :user
  has_many :data_imports, inverse_of: :user
  has_many :geocodings, inverse_of: :user
  has_many :synchronization_oauths, class_name: Carto::SynchronizationOauth, inverse_of: :user, dependent: :destroy
  has_many :search_tweets, inverse_of: :user
  has_many :synchronizations, inverse_of: :user
  has_many :tags, inverse_of: :user
  has_many :permissions, inverse_of: :owner, foreign_key: :owner_id

  has_many :client_applications, class_name: Carto::ClientApplication
  has_many :oauth_tokens, class_name: Carto::OauthToken

  has_many :users_group, dependent: :destroy, class_name: Carto::UsersGroup
  has_many :groups, :through => :users_group

  has_many :received_notifications, inverse_of: :user
  has_many :unread_received_notifications, inverse_of: :user, class_name: Carto::ReceivedNotification,
                                           conditions: { read_at: nil }, order: 'received_at DESC'

  delegate [
      :database_username, :database_password, :in_database,
      :db_size_in_bytes, :get_api_calls, :table_count, :public_visualization_count, :all_visualization_count,
      :visualization_count, :owned_visualization_count, :twitter_imports_count
    ] => :service

  attr_reader :password

  # TODO: From sequel, can be removed once finished
  alias_method :maps_dataset, :maps
  alias_method :layers_dataset, :layers
  alias_method :assets_dataset, :assets
  alias_method :data_imports_dataset, :data_imports
  alias_method :geocodings_dataset, :geocodings

  before_create :set_database_host
  before_create :generate_api_key

  # Auto creates notifications on first access
  def static_notifications_with_creation
    static_notifications_with_creation || build_static_notifications(user: self, notifications: {})
  end
  alias_method_chain :static_notifications, :creation
<commit_msg>Fix infinite recursion<commit_after># encoding: UTF-8

require 'active_record'
require_relative 'user_service'
require_relative 'user_db_service'
require_relative 'synchronization_oauth'
require_relative '../../helpers/data_services_metrics_helper'
require_dependency 'carto/helpers/auth_token_generator'
require_dependency 'carto/helpers/has_connector_configuration'
require_dependency 'carto/helpers/batch_queries_statement_timeout'

# TODO: This probably has to be moved as the service of the proper User Model
class Carto::User < ActiveRecord::Base
  extend Forwardable
  include DataServicesMetricsHelper
  include Carto::AuthTokenGenerator
  include Carto::HasConnectorConfiguration
  include Carto::BatchQueriesStatementTimeout

  MIN_PASSWORD_LENGTH = 6
  MAX_PASSWORD_LENGTH = 64
  GEOCODING_BLOCK_SIZE = 1000
  HERE_ISOLINES_BLOCK_SIZE = 1000
  OBS_SNAPSHOT_BLOCK_SIZE = 1000
  OBS_GENERAL_BLOCK_SIZE = 1000
  MAPZEN_ROUTING_BLOCK_SIZE = 1000

  # INFO: select filter is done for security and performance reasons. Add new columns if needed.
  DEFAULT_SELECT = "users.email, users.username, users.admin, users.organization_id, users.id, users.avatar_url," \
                   "users.api_key, users.database_schema, users.database_name, users.name, users.location," \
                   "users.disqus_shortname, users.account_type, users.twitter_username, users.google_maps_key, " \
                   "users.viewer, users.quota_in_bytes, users.database_host, users.crypted_password, " \
                   "users.builder_enabled, users.private_tables_enabled, users.private_maps_enabled".freeze

  has_many :tables, class_name: Carto::UserTable, inverse_of: :user
  has_many :visualizations, inverse_of: :user
  has_many :maps, inverse_of: :user
  has_many :layers_user
  has_many :layers, through: :layers_user, after_add: Proc.new { |user, layer| layer.set_default_order(user) }

  belongs_to :organization, inverse_of: :users
  has_one :owned_organization, class_name: Carto::Organization, inverse_of: :owner, foreign_key: :owner_id
  has_one :static_notifications, class_name: Carto::UserNotification, inverse_of: :user

  has_many :feature_flags_user, dependent: :destroy, foreign_key: :user_id, inverse_of: :user
  has_many :feature_flags, through: :feature_flags_user
  has_many :assets, inverse_of: :user
  has_many :data_imports, inverse_of: :user
  has_many :geocodings, inverse_of: :user
  has_many :synchronization_oauths, class_name: Carto::SynchronizationOauth, inverse_of: :user, dependent: :destroy
  has_many :search_tweets, inverse_of: :user
  has_many :synchronizations, inverse_of: :user
  has_many :tags, inverse_of: :user
  has_many :permissions, inverse_of: :owner, foreign_key: :owner_id

  has_many :client_applications, class_name: Carto::ClientApplication
  has_many :oauth_tokens, class_name: Carto::OauthToken

  has_many :users_group, dependent: :destroy, class_name: Carto::UsersGroup
  has_many :groups, :through => :users_group

  has_many :received_notifications, inverse_of: :user
  has_many :unread_received_notifications, inverse_of: :user, class_name: Carto::ReceivedNotification,
                                           conditions: { read_at: nil }, order: 'received_at DESC'

  delegate [
      :database_username, :database_password, :in_database,
      :db_size_in_bytes, :get_api_calls, :table_count, :public_visualization_count, :all_visualization_count,
      :visualization_count, :owned_visualization_count, :twitter_imports_count
    ] => :service

  attr_reader :password

  # TODO: From sequel, can be removed once finished
  alias_method :maps_dataset, :maps
  alias_method :layers_dataset, :layers
  alias_method :assets_dataset, :assets
  alias_method :data_imports_dataset, :data_imports
  alias_method :geocodings_dataset, :geocodings

  before_create :set_database_host
  before_create :generate_api_key

  # Auto creates notifications on first access
  def static_notifications_with_creation
    static_notifications_without_creation || build_static_notifications(user: self, notifications: {})
  end
  alias_method_chain :static_notifications, :creation

{'fraction_non_alphanumeric': 0.08108764263170673, 'fraction_numerical': 0.005826656955571741, 'mean_word_length': 5.607056936647955, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7186432', 'n_tokens_mistral': 2656, 'n_tokens_neox': 2542, 'n_words': 570}