Class | Irc::Bot::Auth::BotUser |
In: |
lib/rbot/botuser.rb
|
Parent: | Object |
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. |
login_by_mask | [W] | |
netmasks | [R] | |
password | [R] | |
perm | [R] | |
perm_temp | [R] | |
transient | [W] | |
username | [R] |
Create a new BotUser with given username
# File lib/rbot/botuser.rb, line 284 284: def initialize(username, options={}) 285: opts = {:transient => false}.merge(options) 286: @transient = opts[:transient] 287: 288: if @transient 289: @username = "*" 290: @username << BotUser.sanitize_username(username) if username and not username.to_s.empty? 291: @username << BotUser.sanitize_username(object_id) 292: reset_password 293: @login_by_mask=true 294: @autologin=true 295: else 296: @username = BotUser.sanitize_username(username) 297: @password = nil 298: reset_login_by_mask 299: reset_autologin 300: end 301: 302: @netmasks = NetmaskList.new 303: if opts.key?(:masks) and opts[:masks] 304: masks = opts[:masks] 305: masks = [masks] unless masks.respond_to?(:each) 306: masks.each { |m| 307: mask = m.to_irc_netmask 308: if @transient and User === m 309: mask.nick = "*" 310: mask.host = m.host.dup 311: mask.user = "*" + m.user.sub(/^\w?[^\w]+/,'') 312: end 313: add_netmask(mask) unless mask.to_s == "*" 314: } 315: end 316: raise "must provide a usable mask for transient BotUser #{@username}" if @transient and @netmasks.empty? 317: 318: @perm = {} 319: @perm_temp = {} 320: end
This method sanitizes a username by chomping, downcasing and replacing any nonalphanumeric character with _
# File lib/rbot/botuser.rb, line 518 518: def BotUser.sanitize_username(name) 519: candidate = name.to_s.chomp.downcase.gsub(/[^a-z0-9]/,"_") 520: raise "sanitized botusername #{candidate} too short" if candidate.length < 3 521: return candidate 522: end
# File lib/rbot/botuser.rb, line 245 245: def autologin=(vnew) 246: vold = @autologin 247: @autologin = vnew 248: if vold && !vnew 249: @netmasks.each { |n| Auth.manager.maskdb.remove(self, n) } 250: elsif vnew && !vold 251: @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } 252: end 253: end
Do we allow automatic logging in?
# File lib/rbot/botuser.rb, line 373 373: def autologin? 374: @autologin 375: end
Restore from hash
# File lib/rbot/botuser.rb, line 378 378: def from_hash(h) 379: @username = h[:username] if h.has_key?(:username) 380: @password = h[:password] if h.has_key?(:password) 381: @login_by_mask = h[:login_by_mask] if h.has_key?(:login_by_mask) 382: @autologin = h[:autologin] if h.has_key?(:autologin) 383: if h.has_key?(:netmasks) 384: @netmasks = h[:netmasks] 385: debug @netmasks 386: @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } if @autologin 387: debug @netmasks 388: end 389: @perm = h[:perm] if h.has_key?(:perm) 390: end
Inspection
# File lib/rbot/botuser.rb, line 323 323: def inspect 324: str = self.__to_s__[0..-2] 325: str << " (transient)" if @transient 326: str << ":" 327: str << " @username=#{@username.inspect}" 328: str << " @netmasks=#{@netmasks.inspect}" 329: str << " @perm=#{@perm.inspect}" 330: str << " @perm_temp=#{@perm_temp.inspect}" unless @perm_temp.empty? 331: str << " @login_by_mask=#{@login_by_mask}" 332: str << " @autologin=#{@autologin}" 333: str << ">" 334: 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 500: def login(user, password=nil) 501: if password == @password or (password.nil? and (@login_by_mask || @autologin) and knows?(user)) 502: add_netmask(user) unless knows?(user) 503: debug "#{user} logged in as #{self.inspect}" 504: return true 505: else 506: return false 507: end 508: end
Do we allow logging in without providing the password?
# File lib/rbot/botuser.rb, line 355 355: def login_by_mask? 356: @login_by_mask 357: end
Make the BotUser permanent
# File lib/rbot/botuser.rb, line 271 271: def make_permanent(name) 272: raise TypeError, "permanent already" if permanent? 273: @username = BotUser.sanitize_username(name) 274: @transient = false 275: reset_autologin 276: reset_password # or not? 277: @netmasks.dup.each do |m| 278: delete_netmask(m) 279: add_netmask(m.generalize) 280: end 281: end
This method sets the password if the proposed new password is valid
# File lib/rbot/botuser.rb, line 394 394: def password=(pwd=nil) 395: pass = pwd.to_s 396: if pass.empty? 397: reset_password 398: else 399: begin 400: raise InvalidPassword, "#{pass} contains invalid characters" if pass !~ /^[\x21-\x7e]+$/ 401: raise InvalidPassword, "#{pass} too short" if pass.length < 4 402: @password = pass 403: rescue InvalidPassword => e 404: raise e 405: rescue => e 406: raise InvalidPassword, "Exception #{e.inspect} while checking #{pass.inspect} (#{pwd.inspect})" 407: end 408: end 409: 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 447: def permit?(cmd, chan=nil) 448: if chan 449: k = chan.to_s.to_sym 450: else 451: k = :* 452: end 453: allow = nil 454: pt = @perm.merge @perm_temp 455: if pt.has_key?(k) 456: allow = pt[k].permit?(cmd) 457: end 458: return allow 459: end
Reset the autologin option
# File lib/rbot/botuser.rb, line 367 367: def reset_autologin 368: @autologin = Auth.manager.bot.config['auth.autologin'] unless defined?(@autologin) 369: end
Reset Netmasks, clearing @netmasks
# File lib/rbot/botuser.rb, line 482 482: def reset_netmasks 483: @netmasks.each { |m| 484: Auth.manager.maskdb.remove(self, m) if self.autologin? 485: } 486: @netmasks.clear 487: end
Resets the permission for command cmd on channel chan
# File lib/rbot/botuser.rb, line 426 426: def reset_permission(cmd, chan ="*") 427: set_permission(cmd, nil, chan) 428: end
Resets the temporary permission for command cmd on channel chan
# File lib/rbot/botuser.rb, line 440 440: def reset_temp_permission(cmd, chan ="*") 441: set_temp_permission(cmd, nil, chan) 442: end
Sets the permission for command cmd to val on channel chan
# File lib/rbot/botuser.rb, line 418 418: def set_permission(cmd, val, chan="*") 419: k = chan.to_s.to_sym 420: @perm[k] = PermissionSet.new unless @perm.has_key?(k) 421: @perm[k].set_permission(cmd, val) 422: end
Sets the temporary permission for command cmd to val on channel chan
# File lib/rbot/botuser.rb, line 432 432: def set_temp_permission(cmd, val, chan="*") 433: k = chan.to_s.to_sym 434: @perm_temp[k] = PermissionSet.new unless @perm_temp.has_key?(k) 435: @perm_temp[k].set_permission(cmd, val) 436: end
Convert into a hash
# File lib/rbot/botuser.rb, line 342 342: def to_hash 343: { 344: :username => @username, 345: :password => @password, 346: :netmasks => @netmasks, 347: :perm => @perm, 348: :login_by_mask => @login_by_mask, 349: :autologin => @autologin, 350: } 351: end