<commit_before>require 'digest/sha1'
require 'md5'

# = User accounts
#
# === Users activation and banning
# Users must have the <tt>activated</tt> flag to be able to log in. They will 
# automatically be activated unless manual approval is enabled in the
# configuration. Non-active and banned users won't show up in the users lists.
#
# === Trusted users
# Users with the <tt>trusted</tt> flag can see the trusted categories and 
# discussions. Admin users also count as trusted.

class User < ActiveRecord::Base

	# The attributes in UNSAFE_ATTRIBUTES are blocked from <tt>update_attributes</tt> for regular users.
	UNSAFE_ATTRIBUTES = :id, :username, :hashed_password, :admin, :activated, :banned, :trusted, :user_admin, :moderator, :last_active, :created_at, :updated_at, :posts_count, :discussions_count, :inviter_id, :available_invites

	# Virtual attributes for clear text passwords
	attr_accessor :password, :confirm_password
	attr_accessor :password_changed

	has_many   :discussions, :foreign_key => 'poster_id'
	has_many   :closed_discussions, :foreign_key => 'closer_id'
	has_many   :posts
	belongs_to :inviter, :class_name => 'User'
	has_many   :invitees, :class_name => 'User', :foreign_key => 'inviter_id', :order => 'username ASC'
	has_many   :invites, :dependent => :destroy, :order => 'created_at DESC' do
		def active
			self.select{|i| !i.expired?}
		end
	end
	has_many   :discussion_views, :dependent => :destroy
	has_many   :discussion_relationships, :dependent => :destroy
	has_many   :messages, :foreign_key => 'recipient_id', :conditions => ['deleted = 0'], :order => ['created_at DESC']
	has_many   :unread_messages, :class_name => 'Message', :foreign_key => 'recipient_id', :conditions => ['deleted = 0 AND `read` = 0'], :order => ['created_at DESC']
	has_many   :sent_messages,   :class_name => 'Message', :foreign_key => 'sender_id',    :conditions => ['deleted_by_sender = 0'],      :order => ['created_at DESC']
	has_one    :xbox_info, :dependent => :destroy

	# Automatically generate a password for OpenID users
	before_validation_on_create do |user|
		if user.openid_url? && !user.hashed_password? && (!user.password || user.password.blank?)
			user.generate_password!
		end
	end
	
	validate do |user|
		# Has the password been changed?
		if user.password && !user.password.blank?
			if user.password == user.confirm_password
				new_hashed_password = User.hash_string( user.password )
				# Has the password changed?
				if new_hashed_password != user.hashed_password
					user.hashed_password = <PASSWORD>
					user.password_changed = true
				end
			else
				user.errors.add(:password, "<PASSWORD>")
			end
		end
		# Normalize OpenID URL
		if user.openid_url && !user.openid_url.blank?
			user.openid_url = "http://"+user.openid_url unless user.openid_url =~ /^https?:\/\//
			user.openid_url = OpenID.normalize_url(user.openid_url)
		end
	end

	validates_presence_of   :hashed_password, :unless => :openid_url?
	validates_uniqueness_of :openid_url, :allow_nil => true, :allow_blank => true, :message => 'is already registered.'
	validates_presence_of   :username, :email
	validates_uniqueness_of :username, :message => 'is already registered.'
	validates_format_of     :username, :with => /^[\w\d\-\s_#!]+$/
	validates_presence_of   :realname, :application, :if => Proc.new { |u| Sugar.config(:signup_approval_required) }
	
	class << self
		# Finds active users.
		def find_active
			self.find(:all, :conditions => 'activated = 1 AND banned = 0', :order => 'username ASC')
		end

		# Finds users with activity within some_time. The last_active column is only 
		# updated every 10 minutes, smaller values won't work.<commit_msg>Username uniqueness is now verified regardless of case<commit_after>require 'digest/sha1'
require 'md5'

# = User accounts
#
# === Users activation and banning
# Users must have the <tt>activated</tt> flag to be able to log in. They will 
# automatically be activated unless manual approval is enabled in the
# configuration. Non-active and banned users won't show up in the users lists.
#
# === Trusted users
# Users with the <tt>trusted</tt> flag can see the trusted categories and 
# discussions. Admin users also count as trusted.

class User < ActiveRecord::Base

	# The attributes in UNSAFE_ATTRIBUTES are blocked from <tt>update_attributes</tt> for regular users.
	UNSAFE_ATTRIBUTES = :id, :username, :hashed_password, :admin, :activated, :banned, :trusted, :user_admin, :moderator, :last_active, :created_at, :updated_at, :posts_count, :discussions_count, :inviter_id, :available_invites

	# Virtual attributes for clear text passwords
	attr_accessor :password, :confirm_password
	attr_accessor :password_changed

	has_many   :discussions, :foreign_key => 'poster_id'
	has_many   :closed_discussions, :foreign_key => 'closer_id'
	has_many   :posts
	belongs_to :inviter, :class_name => 'User'
	has_many   :invitees, :class_name => 'User', :foreign_key => 'inviter_id', :order => 'username ASC'
	has_many   :invites, :dependent => :destroy, :order => 'created_at DESC' do
		def active
			self.select{|i| !i.expired?}
		end
	end
	has_many   :discussion_views, :dependent => :destroy
	has_many   :discussion_relationships, :dependent => :destroy
	has_many   :messages, :foreign_key => 'recipient_id', :conditions => ['deleted = 0'], :order => ['created_at DESC']
	has_many   :unread_messages, :class_name => 'Message', :foreign_key => 'recipient_id', :conditions => ['deleted = 0 AND `read` = 0'], :order => ['created_at DESC']
	has_many   :sent_messages,   :class_name => 'Message', :foreign_key => 'sender_id',    :conditions => ['deleted_by_sender = 0'],      :order => ['created_at DESC']
	has_one    :xbox_info, :dependent => :destroy

	# Automatically generate a password for OpenID users
	before_validation_on_create do |user|
		if user.openid_url? && !user.hashed_password? && (!user.password || user.password.blank?)
			user.generate_password!
		end
	end
	
	validate do |user|
		# Has the password been changed?
		if user.password && !user.password.blank?
			if user.password == user.confirm_password
				new_hashed_password = User.hash_string( user.password )
				# Has the password changed?
				if new_hashed_password != user.hashed_password
					user.hashed_password = <PASSWORD>
					user.password_changed = true
				end
			else
				user.errors.add(:password, "must be confirmed")
			end
		end
		# Normalize OpenID URL
		if user.openid_url && !user.openid_url.blank?
			user.openid_url = "http://"+user.openid_url unless user.openid_url =~ /^https?:\/\//
			user.openid_url = OpenID.normalize_url(user.openid_url)
		end
	end

	validates_presence_of   :hashed_password, :unless => :openid_url?
	validates_uniqueness_of :openid_url, :allow_nil => true, :allow_blank => true, :message => 'is already registered.', :case_sensitive => false
	validates_presence_of   :username, :email
	validates_uniqueness_of :username, :message => 'is already registered.', :case_sensitive => false
	validates_format_of     :username, :with => /^[\w\d\-\s_#!]+$/
	validates_presence_of   :realname, :application, :if => Proc.new { |u| Sugar.config(:signup_approval_required) }
	
	class << self
		# Finds active users.
		def find_active
			self.find(:all, :conditions => 'activated = 1 AND banned = 0', :order => 'username ASC')
		end

		# Finds users with activity within some_time. The last_active column is only 
		# updated every 10 minutes, smaller values won't work.
{'fraction_non_alphanumeric': 0.12214151197202044, 'fraction_numerical': 0.0026903416733925207, 'mean_word_length': 4.701687116564417, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 82, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4356896', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2400, 'n_words': 676}