app/models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable, :lockable and :timeoutable
devise :database_authenticatable, :registerable, :omniauthable,
:recoverable, :rememberable, :trackable, :validatable
# Tags hated by the user
acts_as_taggable_on :hates
acts_as_taggable_on :likes
has_and_belongs_to_many :single_events, -> { uniq }
has_many :event_curations
has_many :curated_events, :through => :event_curations, :source => :event
has_many :region_organizers
has_many :assigned_regions, :through => :region_organizers, :source => :region
belongs_to :current_region, class_name: "Region"
#OmniAuth Authorizations
has_many :authorizations
# Setup accessible (or protected) attributes for your model
# Temporary auth token and method to store it when we are done :)
attr_accessor :auth_temp_token
after_save :associate_auth_token_with_account
validates :nickname, uniqueness: true
validates :nickname, presence: true
validates :email, presence: true
validates :email, uniqueness: true
validates_exclusion_of :nickname, in: %w(admin root administrator superuser), message: I18n.t('devise.registrations.exclusion')
validate :username_format
before_save :try_to_fix_urls
default_scope -> { order(:nickname) }
def organized_regions
if self.admin
Region.all
else
assigned_regions
end
end
def to_param
nickname
end
def username_format
has_one_letter = nickname =~ /[a-zA-Z]/
all_valid_characters = nickname =~ /^[a-zA-Z0-9_]+$/
errors.add(:nickname, I18n.t('devise.registrations.format')) unless (has_one_letter and all_valid_characters)
end
# http://stackoverflow.com/questions/2997179/ror-devise-sign-in-with-username-or-email
def self.find_for_database_authentication(conditions={})
self.where("nickname = ?", conditions[:email]).limit(1).first ||
self.where("email = ?", conditions[:email]).limit(1).first
end
def update_with_password_pass(params={})
if params[:password].blank? and params[:email] == self.email
params.delete(:current_password)
params.delete(:password)
params.delete(:password_confirmation)
self.update_without_password(params)
else
current_password = params.delete(:current_password)
params.delete(:password) if params[:password].blank?
params.delete(:password_confirmation) if params[:password_confirmation].blank?
result = if valid_password?(current_password)
update_attributes(params)
else
self.attributes = params
self.valid?
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false
end
clean_up_passwords
result
end
end
# This is required for the oauth stuff
def update_with_password(params, *options)
if encrypted_password.blank?
update_attributes(params.except(:current_password), *options)
else
update_with_password_pass(params)
end
end
def allow_ignore_view?
!!self.allow_ignore_view
end
def guid
guid = read_attribute :guid
if guid.blank?
begin
guid = (0..16).to_a.map {|a| rand(16).to_s(16)}.join
end while User.where('guid = ?', guid).count > 0
write_attribute :guid, guid
self.save
end
return guid
end
# Detects if a user likes a single event
#
# This is the case if the user has more tags from the event-taglist in his
# like-list than in his hate-list.
#
# @param [SingleEvent] single_event the event you want to check
# @return [Boolean]
def likes?(single_event)
event_tags = single_event.tag_list + single_event.event.tag_list
(event_tags & self.like_list).size > (event_tags & self.hate_list).size
end
def self.current
Thread.current[:user]
end
def self.current=(user)
Thread.current[:user] = user
end
# Functions for Devise & Omniauth
# Create a user from an OmniAuth request
def self.from_omniauth(auth)
auth_token = Authorization.where(provider: auth.provider, uid: auth.uid).first
# If we have a token without an associated user (user canceled signup), we delete it and the user has to sign up
if (auth_token && auth_token.user.nil?)
auth_token.destroy
auth_token = nil
end
if auth_token
# If there is an OAuth token attached we refresh the one we have in the database
auth_token.update_attributes(Authorization.extract_auth_data(auth))
auth_token.user
else
temp_token = Authorization.create_authorization(auth).temp_token
user = self.create(nickname: auth.info.nickname, email: auth.info.email, image_url: auth.info.image, auth_temp_token: temp_token)
user
end
end
# Create a user with the devise session
def self.new_with_session(params, session)
if session["devise.user_attributes"]
self.new(session["devise.user_attributes"]) do |user|
user.attributes = params
user.valid?
end
else
super
end
end
# Password is only required if no authorizations are present
# or if no temp token is associated with the account
def password_required?
super && authorizations.length == 0 && !auth_temp_token
end
# E-Mail is only required if no authorizations are present
# or if no temp token is associated with the account
def email_required?
authorizations.length == 0 && !auth_temp_token
end
def to_s
nickname
end
# This method checks if there is only one authorization left and the user has no password
def needs_one_authorization?
self.encrypted_password.blank? && self.authorizations.count == 1
end
def available_providers
User.omniauth_providers - self.authorizations.map{ |a| a.provider.to_sym }
end
def set_external_nickname(ext_nick, force = false)
ext_nick = ext_nick.select {|ext,nick| [:github, :twitter].include?(ext)}
ext_nick = ext_nick.select {|ext,nick| self.send(ext).blank?} unless force
self.update_attributes(ext_nick)
end
private
def try_to_fix_urls
if twitter && m = twitter.match(/(?:http:\/\/)?twitter.com\/(.*)/)
self.twitter = m[1]
end
if github && m = github.match(/(?:http:\/\/)?github.com\/(.*)/)
self.github = m[1]
end
if homepage.present? && !homepage.match(/\Ahttp(s)?:\/\//)
self.homepage = "http://#{homepage}"
end
end
def associate_auth_token_with_account
if auth_temp_token
a = Authorization.find_by_temp_token(auth_temp_token)
self.auth_temp_token = nil
unless a.nil?
a.temp_token = nil
a.user = self
a.save!
end
end
end
end