class Irc::Bot::Auth::BotUser

This is the basic class for bot users: they have a username, a password, a list of netmasks to match against, and a list of permissions. A BotUser can be marked as ‘transient’, usually meaning it’s not intended for permanent storage. Transient BotUsers have lower priority than nontransient ones for autologin purposes.

To initialize a BotUser, you pass a username and an optional hash of options. Currently, only two options are recognized:

transient

true or false, determines if the BotUser is transient or permanent (default is false, permanent BotUser).

Transient BotUsers are initialized by prepending an asterisk (*) to the username, and appending a sanitized version of the object_id. The username can be empty. A random password is generated.

Permanent Botusers need the username as is, and no password is generated.

masks

an array of Netmasks to initialize the NetmaskList. This list is used as-is for permanent BotUsers.

Transient BotUsers will alter the list elements which are Irc::User by globbing the nick and any initial nonletter part of the ident.

The masks option is optional for permanent BotUsers, but obligatory (non-empty) for transients.

We extend the BotUser class to handle remote logins

Attributes

login_by_mask[W]
netmasks[R]
password[R]
perm[R]
perm_temp[R]
transient[W]
username[R]

Public Class Methods

new(username, options={}) click to toggle source

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
sanitize_username(name) click to toggle source

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

Public Instance Methods

autologin=(vnew) click to toggle source
# 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
autologin?() click to toggle source

Do we allow automatic logging in?

# File lib/rbot/botuser.rb, line 373
def autologin?
  @autologin
end
default?() click to toggle source

Check if the current BotUser is the default one

# File lib/rbot/botuser.rb, line 636
def default?
  return DefaultBotUserClass === self
end
from_hash(h) click to toggle source

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
inspect() click to toggle source

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
knows?(usr) click to toggle source

This method checks if BotUser has a Netmask that matches user

# File lib/rbot/botuser.rb, line 491
def knows?(usr)
  user = usr.to_irc_user
  !!@netmasks.find { |n| user.matches? n }
end
login(user, password=nil) click to toggle source

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
login_by_mask?() click to toggle source

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_permanent(name) click to toggle source

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
owner?() click to toggle source

Check if the current BotUser is the owner

# File lib/rbot/botuser.rb, line 641
def owner?
  return BotOwnerClass === self
end
password=(pwd=nil) click to toggle source

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
permanent=(bool) click to toggle source

Sets if the BotUser is permanent or not

# File lib/rbot/botuser.rb, line 266
def permanent=(bool)
  @transient=!bool
end
permanent?() click to toggle source

Checks if the BotUser is permanent (not transient)

# File lib/rbot/botuser.rb, line 261
def permanent?
  !@transient
end
permit?(cmd, chan=nil) click to toggle source

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
remote_login(password) click to toggle source

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_autologin() click to toggle source

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_login_by_mask() click to toggle source

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() click to toggle source

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
reset_password() click to toggle source

Resets the password by creating a new onw

# File lib/rbot/botuser.rb, line 412
def reset_password
  @password = Auth.random_password
end
reset_permission(cmd, chan ="*") click to toggle source

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
reset_temp_permission(cmd, chan ="*") click to toggle source

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
set_permission(cmd, val, chan="*") click to toggle source

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
set_temp_permission(cmd, val, chan="*") click to toggle source

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
to_hash() click to toggle source

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
to_s() click to toggle source

In strings

# File lib/rbot/botuser.rb, line 337
def to_s
  @username
end
transient?() click to toggle source

Checks if the BotUser is transient

# File lib/rbot/botuser.rb, line 256
def transient?
  @transient
end

Private Instance Methods

add_netmask(mask) click to toggle source

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
delete_netmask(mask) click to toggle source

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