We extend the BotUser class to handle remote logins
Create a new BotUser with given username
# File lib/rbot/botuser.rb, line 284 def initialize(username, options={}) opts = {:transient => false}.merge(options) @transient = opts[:transient] if @transient @username = "*" @username << BotUser.sanitize_username(username) if username and not username.to_s.empty? @username << BotUser.sanitize_username(object_id) reset_password @login_by_mask=true @autologin=true else @username = BotUser.sanitize_username(username) @password = nil reset_login_by_mask reset_autologin end @netmasks = NetmaskList.new if opts.key?(:masks) and opts[:masks] masks = opts[:masks] masks = [masks] unless masks.respond_to?(:each) masks.each { |m| mask = m.to_irc_netmask if @transient and User === m mask.nick = "*" mask.host = m.host.dup mask.user = "*" + m.user.sub(/^\w?[^\w]+/,'') end add_netmask(mask) unless mask.to_s == "*" } end raise "must provide a usable mask for transient BotUser #{@username}" if @transient and @netmasks.empty? @perm = {} @perm_temp = {} end
This method sanitizes a username by chomping, downcasing and replacing any nonalphanumeric character with _
# File lib/rbot/botuser.rb, line 518 def BotUser.sanitize_username(name) candidate = name.to_s.chomp.downcase.gsub(/[^a-z0-9]/,"_") raise "sanitized botusername #{candidate} too short" if candidate.length < 3 return candidate end
# File lib/rbot/botuser.rb, line 245 def autologin=(vnew) vold = @autologin @autologin = vnew if vold && !vnew @netmasks.each { |n| Auth.manager.maskdb.remove(self, n) } elsif vnew && !vold @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } end end
Do we allow automatic logging in?
# File lib/rbot/botuser.rb, line 373 def autologin? @autologin end
Check if the current BotUser is the default one
# File lib/rbot/botuser.rb, line 636 def default? return DefaultBotUserClass === self end
Restore from hash
# File lib/rbot/botuser.rb, line 378 def from_hash(h) @username = h[:username] if h.has_key?(:username) @password = h[:password] if h.has_key?(:password) @login_by_mask = h[:login_by_mask] if h.has_key?(:login_by_mask) @autologin = h[:autologin] if h.has_key?(:autologin) if h.has_key?(:netmasks) @netmasks = h[:netmasks] debug @netmasks @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } if @autologin debug @netmasks end @perm = h[:perm] if h.has_key?(:perm) end
Inspection
# File lib/rbot/botuser.rb, line 323 def inspect str = self.__to_s__[0..-2] str << " (transient)" if @transient str << ":" str << " @username=#{@username.inspect}" str << " @netmasks=#{@netmasks.inspect}" str << " @perm=#{@perm.inspect}" str << " @perm_temp=#{@perm_temp.inspect}" unless @perm_temp.empty? str << " @login_by_mask=#{@login_by_mask}" str << " @autologin=#{@autologin}" str << ">" end
This method gets called when User user wants to log in. It returns true or false depending on whether the password is right. If it is, the Netmask of the user is added to the list of acceptable Netmask unless it's already matched.
# File lib/rbot/botuser.rb, line 500 def login(user, password=nil) if password == @password or (password.nil? and (@login_by_mask || @autologin) and knows?(user)) add_netmask(user) unless knows?(user) debug "#{user} logged in as #{self.inspect}" return true else return false end end
Do we allow logging in without providing the password?
# File lib/rbot/botuser.rb, line 355 def login_by_mask? @login_by_mask end
Make the BotUser permanent
# File lib/rbot/botuser.rb, line 271 def make_permanent(name) raise TypeError, "permanent already" if permanent? @username = BotUser.sanitize_username(name) @transient = false reset_autologin reset_password # or not? @netmasks.dup.each do |m| delete_netmask(m) add_netmask(m.generalize) end end
Check if the current BotUser is the owner
# File lib/rbot/botuser.rb, line 641 def owner? return BotOwnerClass === self end
This method sets the password if the proposed new password is valid
# File lib/rbot/botuser.rb, line 394 def password=(pwd=nil) pass = pwd.to_s if pass.empty? reset_password else begin raise InvalidPassword, "#{pass} contains invalid characters" if pass !~ /^[\x21-\x7e]+$/ raise InvalidPassword, "#{pass} too short" if pass.length < 4 @password = pass rescue InvalidPassword => e raise e rescue => e raise InvalidPassword, "Exception #{e.inspect} while checking #{pass.inspect} (#{pwd.inspect})" end end end
Sets if the BotUser is permanent or not
# File lib/rbot/botuser.rb, line 266 def permanent=(bool) @transient=!bool end
Checks if the BotUser is permanent (not transient)
# File lib/rbot/botuser.rb, line 261 def permanent? !@transient end
Checks if BotUser is allowed to do something on channel chan, or on all channels if chan is nil
# File lib/rbot/botuser.rb, line 447 def permit?(cmd, chan=nil) if chan k = chan.to_s.to_sym else k = :* end allow = nil pt = @perm.merge @perm_temp if pt.has_key?(k) allow = pt[k].permit?(cmd) end return allow end
A rather simple method to handle remote logins. Nothing special, just a password check.
# File lib/rbot/core/remote.rb, line 27 def remote_login(password) if password == @password debug "remote login for #{self.inspect} succeeded" return true else return false end end
Reset the autologin option
# File lib/rbot/botuser.rb, line 367 def reset_autologin @autologin = Auth.manager.bot.config['auth.autologin'] unless defined?(@autologin) end
Reset the login-by-mask option
# File lib/rbot/botuser.rb, line 361 def reset_login_by_mask @login_by_mask = Auth.manager.bot.config['auth.login_by_mask'] unless defined?(@login_by_mask) end
Reset Netmasks, clearing @netmasks
# File lib/rbot/botuser.rb, line 482 def reset_netmasks @netmasks.each { |m| Auth.manager.maskdb.remove(self, m) if self.autologin? } @netmasks.clear end
Resets the password by creating a new onw
# File lib/rbot/botuser.rb, line 412 def reset_password @password = Auth.random_password end
Resets the permission for command cmd on channel chan
# File lib/rbot/botuser.rb, line 426 def reset_permission(cmd, chan ="*") set_permission(cmd, nil, chan) end
Resets the temporary permission for command cmd on channel chan
# File lib/rbot/botuser.rb, line 440 def reset_temp_permission(cmd, chan ="*") set_temp_permission(cmd, nil, chan) end
Sets the permission for command cmd to val on channel chan
# File lib/rbot/botuser.rb, line 418 def set_permission(cmd, val, chan="*") k = chan.to_s.to_sym @perm[k] = PermissionSet.new unless @perm.has_key?(k) @perm[k].set_permission(cmd, val) end
Sets the temporary permission for command cmd to val on channel chan
# File lib/rbot/botuser.rb, line 432 def set_temp_permission(cmd, val, chan="*") k = chan.to_s.to_sym @perm_temp[k] = PermissionSet.new unless @perm_temp.has_key?(k) @perm_temp[k].set_permission(cmd, val) end
Convert into a hash
# File lib/rbot/botuser.rb, line 342 def to_hash { :username => @username, :password => @password, :netmasks => @netmasks, :perm => @perm, :login_by_mask => @login_by_mask, :autologin => @autologin, } end
In strings
# File lib/rbot/botuser.rb, line 337 def to_s @username end
Checks if the BotUser is transient
# File lib/rbot/botuser.rb, line 256 def transient? @transient end
Adds a Netmask
# File lib/rbot/botuser.rb, line 463 def add_netmask(mask) m = mask.to_irc_netmask @netmasks << m if self.autologin? Auth.manager.maskdb.add(self, m) Auth.manager.logout_transients(m) if self.permanent? end end
Removes a Netmask
# File lib/rbot/botuser.rb, line 474 def delete_netmask(mask) m = mask.to_irc_netmask @netmasks.delete(m) Auth.manager.maskdb.remove(self, m) if self.autologin? end