Class: Irc::Bot::Auth::ManagerClass

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/rbot/botuser.rb,
lib/rbot/core/remote.rb

Overview

We extend the ManagerClass to handle remote logins

Constant Summary collapse

MAX_SESSION_ID =
2**128 - 1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeManagerClass

The instance manages two Hashes: one that maps Irc::Users onto BotUsers, and the other that maps usernames onto BotUser



662
663
664
665
666
# File 'lib/rbot/botuser.rb', line 662

def initialize
  @everyone = Auth::defaultbotuser
  @botowner = Auth::botowner
  bot_associate(nil)
end

Instance Attribute Details

#botObject (readonly)

Returns the value of attribute bot.



657
658
659
# File 'lib/rbot/botuser.rb', line 657

def bot
  @bot
end

#botownerObject (readonly)

Returns the value of attribute botowner.



656
657
658
# File 'lib/rbot/botuser.rb', line 656

def botowner
  @botowner
end

#everyoneObject (readonly)

Returns the value of attribute everyone.



655
656
657
# File 'lib/rbot/botuser.rb', line 655

def everyone
  @everyone
end

#maskdbObject (readonly)

Returns the value of attribute maskdb.



654
655
656
# File 'lib/rbot/botuser.rb', line 654

def maskdb
  @maskdb
end

Instance Method Details

#allow?(cmdtxt, user, chan = nil) ⇒ Boolean

Checks if command cmd is allowed to User user on chan, optionally telling if the user is authorized

Returns:

  • (Boolean)


907
908
909
910
911
912
913
914
915
916
917
# File 'lib/rbot/botuser.rb', line 907

def allow?(cmdtxt, user, chan=nil)
  if permit?(user, cmdtxt, chan)
    return true
  else
    # cmds = cmdtxt.split('::')
    # @bot.say chan, "you don't have #{cmds.last} (#{cmds.first}) permissions here" if chan
    @bot.say chan, _("%{user}, you don't have '%{command}' permissions here") %
                  {:user=>user, :command=>cmdtxt} if chan
    return false
  end
end

#autologin(user) ⇒ Object

Tries to auto-login Irc::User user by looking at the known botusers that allow autologin and trying to login without a password



783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
# File 'lib/rbot/botuser.rb', line 783

def autologin(user)
  ircuser = user.to_irc_user
  debug "Trying to autologin #{ircuser}"
  return @botusers[ircuser] if @botusers.has_key?(ircuser)
  bu = maskdb.find(ircuser)
  if bu
    debug "trying #{bu}"
    bu.(ircuser) or raise '...what?!'
    @botusers[ircuser] = bu
    return bu
  end
  # Finally, create a transient if we're set to allow it
  if @bot.config['auth.autouser']
    bu = create_transient_botuser(ircuser)
    @botusers[ircuser] = bu
    return bu
  end
  return everyone
end

#bot_associate(bot) ⇒ Object



668
669
670
671
672
673
674
675
676
677
678
679
# File 'lib/rbot/botuser.rb', line 668

def bot_associate(bot)
  raise "Cannot associate with a new bot! Save first" if defined?(@has_changes) && @has_changes

  reset_hashes

  # Associated bot
  @bot = bot

  # This variable is set to true when there have been changes
  # to the botusers list, so that we know when to save
  @has_changes = false
end

#changed?Boolean

Returns:

  • (Boolean)


689
690
691
# File 'lib/rbot/botuser.rb', line 689

def changed?
  @has_changes
end

#create_botuser(name, password = nil) ⇒ Object

creates a new BotUser



741
742
743
744
745
746
747
748
749
# File 'lib/rbot/botuser.rb', line 741

def create_botuser(name, password=nil)
  n = BotUser.sanitize_username(name)
  k = n.to_sym
  raise "botuser #{n} exists" if include?(k)
  bu = BotUser.new(n)
  bu.password = password
  @allbotusers[k] = bu
  return bu
end

#create_transient_botuser(user) ⇒ Object

Creates a new transient BotUser associated with Irc::User user, automatically logging him in. Note that transient botuser creation can fail, typically if we don’t have the complete user netmask (e.g. for messages coming in from a linkbot)



808
809
810
811
812
813
814
815
816
817
818
819
# File 'lib/rbot/botuser.rb', line 808

def create_transient_botuser(user)
  ircuser = user.to_irc_user
  bu = everyone
  begin
    bu = BotUser.new(ircuser, :transient => true, :masks => ircuser)
    bu.(ircuser)
  rescue
    warning "failed to create transient for #{user}"
    error $!
  end
  return bu
end

#get_botuser(name) ⇒ Object

returns the botuser with name name



752
753
754
# File 'lib/rbot/botuser.rb', line 752

def get_botuser(name)
  @allbotusers.fetch(BotUser.sanitize_username(name).to_sym)
end

#include?(botusername) ⇒ Boolean

checks if we know about a certain BotUser username

Returns:

  • (Boolean)


729
730
731
# File 'lib/rbot/botuser.rb', line 729

def include?(botusername)
  @allbotusers.has_key?(botusername.to_sym)
end

#irc_to_botuser(ircuser) ⇒ Object

Maps Irc::User to BotUser



734
735
736
737
738
# File 'lib/rbot/botuser.rb', line 734

def irc_to_botuser(ircuser)
  logged = @botusers[ircuser.to_irc_user]
  return logged if logged
  return autologin(ircuser)
end

#load_array(ary, forced) ⇒ Object



703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
# File 'lib/rbot/botuser.rb', line 703

def load_array(ary, forced)
  unless ary
    warning "Tried to load an empty array"
    return
  end
  raise "Won't load with unsaved changes" if @has_changes and not forced
  reset_hashes
  ary.each { |x|
    raise TypeError, "#{x} should be a Hash" unless x.kind_of?(Hash)
    u = x[:username]
    unless include?(u)
      create_botuser(u)
    end
    get_botuser(u).from_hash(x)
    get_botuser(u).transient = false
  }
  @has_changes=false
end

#login(user, botusername, pwd = nil) ⇒ Object

Logs Irc::User user in to BotUser botusername with password pwd

raises an error if botusername is not a known BotUser username

It is possible to autologin by Netmask, on request



762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# File 'lib/rbot/botuser.rb', line 762

def (user, botusername, pwd=nil)
  ircuser = user.to_irc_user
  n = BotUser.sanitize_username(botusername)
  k = n.to_sym
  raise "No such BotUser #{n}" unless include?(k)
  if @botusers.has_key?(ircuser)
    return true if @botusers[ircuser].username == n
    # TODO
    # @botusers[ircuser].logout(ircuser)
  end
  bu = @allbotusers[k]
  if bu.(ircuser, pwd)
    @botusers[ircuser] = bu
    return true
  end
  return false
end

#logout_transients(m) ⇒ Object

Logs out any Irc::User matching Irc::Netmask m and logged in to a transient BotUser



824
825
826
827
828
829
830
831
832
833
# File 'lib/rbot/botuser.rb', line 824

def logout_transients(m)
  debug "to check: #{@botusers.keys.join ' '}"
  @botusers.keys.each do |iu|
    debug "checking #{iu.fullform} against #{m.fullform}"
    bu = @botusers[iu]
    bu.transient? or next
    iu.matches?(m) or next
    @botusers.delete(iu).autologin = false
  end
end

#make_permanent(user, name) ⇒ Object

Makes transient BotUser user into a permanent BotUser named name; if user is an Irc::User, act on the transient BotUser (if any) it’s logged in as

Raises:

  • (TypeError)


839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
# File 'lib/rbot/botuser.rb', line 839

def make_permanent(user, name)
  buname = BotUser.sanitize_username(name)
  # TODO merge BotUser instead?
  raise "there's already a BotUser called #{name}" if include?(buname)

  tuser = nil
  case user
  when String, Irc::User
    tuser = irc_to_botuser(user)
  when BotUser
    tuser = user
  else
    raise TypeError, "sorry, don't know how to make #{user.class} into a permanent BotUser"
  end
  return nil unless tuser
  raise TypeError, "#{tuser} is not transient" unless tuser.transient?

  tuser.make_permanent(buname)
  @allbotusers[tuser.username.to_sym] = tuser

  return tuser
end

#permit?(user, cmdtxt, channel = nil) ⇒ Boolean

Checks if User user can do cmd on chan.

Permission are checked in this order, until a true or false is returned:

  • associated BotUser on chan

  • associated BotUser on all channels

  • everyone on chan

  • everyone on all channels

Returns:

  • (Boolean)


871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
# File 'lib/rbot/botuser.rb', line 871

def permit?(user, cmdtxt, channel=nil)
  if user.class <= BotUser
    botuser = user
  else
    botuser = irc_to_botuser(user)
  end
  cmd = cmdtxt.to_irc_auth_command

  chan = channel
  case chan
  when User
    chan = "?"
  when Channel
    chan = chan.name
  end

  allow = nil

  allow = botuser.permit?(cmd, chan) if chan
  return allow unless allow.nil?
  allow = botuser.permit?(cmd)
  return allow unless allow.nil?

  unless botuser == everyone
    allow = everyone.permit?(cmd, chan) if chan
    return allow unless allow.nil?
    allow = everyone.permit?(cmd)
    return allow unless allow.nil?
  end

  raise "Could not check permission for user #{user.inspect} to run #{cmdtxt.inspect} on #{chan.inspect}"
end

#remote_login(botusername, pwd) ⇒ Object

Creates a session id when the given password matches the given botusername



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rbot/core/remote.rb', line 46

def (botusername, pwd)
  @remote_users = Hash.new unless defined? @remote_users
  n = BotUser.sanitize_username(botusername)
  k = n.to_sym
  raise "No such BotUser #{n}" unless include?(k)
  bu = @allbotusers[k]
  if bu.(pwd)
    raise "ran out of session ids!" if @remote_users.length == MAX_SESSION_ID
    session_id = rand(MAX_SESSION_ID)
    while @remote_users.has_key?(session_id)
      session_id = rand(MAX_SESSION_ID)
    end
    @remote_users[session_id] = bu
    return session_id
  end
  return false
end

#remote_user(session_id) ⇒ Object

Returns the botuser associated with the given session id



65
66
67
68
69
70
71
72
73
# File 'lib/rbot/core/remote.rb', line 65

def remote_user(session_id)
  return everyone unless session_id
  return nil unless defined? @remote_users
  if @remote_users.has_key?(session_id)
    return @remote_users[session_id]
  else
    return nil
  end
end

#reset_changedObject



685
686
687
# File 'lib/rbot/botuser.rb', line 685

def reset_changed
  @has_changes = false
end

#reset_hashesObject

resets the hashes



694
695
696
697
698
699
700
701
# File 'lib/rbot/botuser.rb', line 694

def reset_hashes
  @botusers = Hash.new
  @maskdb = NetmaskDb.new
  @allbotusers = Hash.new
  [everyone, botowner].each do |x|
    @allbotusers[x.username.to_sym] = x
  end
end

#save_arrayObject



722
723
724
725
726
# File 'lib/rbot/botuser.rb', line 722

def save_array
  @allbotusers.values.map { |x|
    x.transient? ? nil : x.to_hash
  }.compact
end

#set_changedObject



681
682
683
# File 'lib/rbot/botuser.rb', line 681

def set_changed
  @has_changes = true
end