Add a Restricted user level. Restricted users are level 10, below Members. New users start out as Restricted if they sign up from a proxy or an IP recently used by another user. Restricted users can't update or edit any public content on the site until they verify their email address, at which point they're promoted to Member. Restricted users are only allowed to do personal actions like keep favorites, keep favgroups and saved searches, mark dmails as read or deleted, or mark forum posts as read. The restricted state already existed before, the only change here is that now it's an actual user level instead of a hidden state. Before it was based on two hidden flags on the user, the `requires_verification` flag (set when a user signs up from a proxy, etc), and the `is_verified` flag (set after the user verifies their email). Making it a user level means that now the Restricted status will be shown publicly. Introducing a new level below Member means that we have to change every `is_member?` check to `!is_anonymous` for every place where we used `is_member?` to check that the current user is logged in.
64 lines
1.5 KiB
Ruby
64 lines
1.5 KiB
Ruby
# Checks whether a new account seems suspicious and should require email verification.
|
|
|
|
class UserVerifier
|
|
extend Memoist
|
|
|
|
attr_reader :current_user, :request
|
|
|
|
# current_user is the user creating the new account, not the new account itself.
|
|
def initialize(current_user, request)
|
|
@current_user, @request = current_user, request
|
|
end
|
|
|
|
def requires_verification?
|
|
return false if !Danbooru.config.new_user_verification?
|
|
return false if is_local_ip?
|
|
|
|
# we check for IP bans first to make sure we bump the IP ban hit count
|
|
is_ip_banned? || is_logged_in? || is_recent_signup? || is_proxy?
|
|
end
|
|
|
|
def initial_level
|
|
if requires_verification?
|
|
User::Levels::RESTRICTED
|
|
else
|
|
User::Levels::MEMBER
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def ip_address
|
|
@ip_address ||= IPAddress.parse(request.remote_ip)
|
|
end
|
|
|
|
def is_local_ip?
|
|
if ip_address.ipv4?
|
|
ip_address.loopback? || ip_address.link_local? || ip_address.private?
|
|
elsif ip_address.ipv6?
|
|
ip_address.loopback? || ip_address.link_local? || ip_address.unique_local?
|
|
end
|
|
end
|
|
|
|
def is_logged_in?
|
|
!current_user.is_anonymous?
|
|
end
|
|
|
|
def is_recent_signup?(age: 24.hours)
|
|
subnet_len = ip_address.ipv4? ? 24 : 64
|
|
subnet = "#{ip_address}/#{subnet_len}"
|
|
|
|
User.where("last_ip_addr <<= ?", subnet).where("created_at > ?", age.ago).exists?
|
|
end
|
|
|
|
def is_ip_banned?
|
|
IpBan.hit!(:partial, ip_address.to_s)
|
|
end
|
|
|
|
def is_proxy?
|
|
IpLookup.new(ip_address).is_proxy?
|
|
end
|
|
|
|
memoize :is_ip_banned?, :is_proxy?, :is_recent_signup?
|
|
end
|