| 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