diff options
author | Giuseppe Bilotta <giuseppe.bilotta@gmail.com> | 2006-08-02 16:26:29 +0000 |
---|---|---|
committer | Giuseppe Bilotta <giuseppe.bilotta@gmail.com> | 2006-08-02 16:26:29 +0000 |
commit | c9b76ddbc6ada354e0c1f14a14fcd1cdd7c1230c (patch) | |
tree | aa4a4a5a0648a5ec09d8c9a7036d79cb44d2d39d /lib | |
parent | 7bef95455cfbec9cf77db283a11e177f4c981b6a (diff) |
Auth now follows the specs defined in NewAuthModule even though there is no actual auth coremodule. config.rb needs to be split into a class definition file and a coremodule that manages it
Diffstat (limited to 'lib')
-rw-r--r-- | lib/rbot/botuser.rb | 86 | ||||
-rw-r--r-- | lib/rbot/config.rb | 33 | ||||
-rw-r--r-- | lib/rbot/core/core.rb | 61 | ||||
-rw-r--r-- | lib/rbot/ircbot.rb | 1 | ||||
-rw-r--r-- | lib/rbot/messagemapper.rb | 46 | ||||
-rw-r--r-- | lib/rbot/plugins.rb | 71 |
6 files changed, 206 insertions, 92 deletions
diff --git a/lib/rbot/botuser.rb b/lib/rbot/botuser.rb index 98408a0d..6c84a93b 100644 --- a/lib/rbot/botuser.rb +++ b/lib/rbot/botuser.rb @@ -252,13 +252,29 @@ module Irc @perm = {}
end
+ # Inspection simply inspects the internal hash
+ def inspect
+ @perm.inspect
+ end
+
# Sets the permission for command _cmd_ to _val_,
- # creating intermediate permissions if needed.
#
def set_permission(cmd, val)
- raise TypeError, "#{val.inspect} must be true or false" unless [true,false].include?(val)
Irc::error_if_not_command(cmd)
- @perm[cmd.command] = val
+ case val
+ when true, false
+ @perm[cmd.command] = val
+ when nil
+ @perm.delete(cmd.command)
+ else
+ raise TypeError, "#{val.inspect} must be true or false" unless [true,false].include?(val)
+ end
+ end
+
+ # Resets the permission for command _cmd_
+ #
+ def reset_permission(cmd)
+ set_permission(cmd, nil)
end
# Tells if command _cmd_ is permitted. We do this by returning
@@ -313,6 +329,12 @@ module Irc end
end
+ # Resets the permission for command _cmd_ on channel _chan_
+ #
+ def reset_permission(cmd, chan ="*")
+ set_permission(cmd, nil, chan)
+ end
+
# Checks if BotUser is allowed to do something on channel _chan_,
# or on all channels if _chan_ is nil
#
@@ -415,17 +437,27 @@ module Irc end
- # This is the anonymous BotUser: it's used for all users which haven't
+ # This is the default BotUser: it's used for all users which haven't
# identified with the bot
#
- class AnonBotUserClass < BotUser
+ class DefaultBotUserClass < BotUser
include Singleton
def initialize
- super("anonymous")
+ super("everyone")
+ @default_perm = PermissionSet.new
end
private :login, :add_netmask, :delete_netmask
- # Anon knows everybody
+ # Sets the default permission for the default user (i.e. the ones
+ # set by the BotModule writers) on all channels
+ #
+ def set_default_permission(cmd, val)
+ @default_perm.set_permission(Command.new(cmd), val)
+ debug "Default permissions now:\n#{@default_perm.inspect}"
+ end
+
+ # default knows everybody
+ #
def knows?(user)
Irc::error_if_not_user(user)
return true
@@ -436,12 +468,24 @@ module Irc super
add_netmask("*!*@*")
end
+
+ # DefaultBotUser will check the default_perm after checking
+ # the global ones
+ # or on all channels if _chan_ is nil
+ #
+ def permit?(cmd, chan=nil)
+ allow = super(cmd, chan)
+ if allow.nil? && chan.nil?
+ allow = @default_perm.permit?(cmd)
+ end
+ return allow
+ end
end
- # Returns the only instance of AnonBotUserClass
+ # Returns the only instance of DefaultBotUserClass
#
- def Auth.anonbotuser
- return AnonBotUserClass.instance
+ def Auth.defaultbotuser
+ return DefaultBotUserClass.instance
end
# This is the BotOwner: he can do everything
@@ -470,10 +514,15 @@ module Irc class AuthManagerClass
include Singleton
+ attr_reader :everyone
+ attr_reader :botowner
+
# The instance manages two <code>Hash</code>es: one that maps
# <code>Irc::User</code>s onto <code>BotUser</code>s, and the other that maps
# usernames onto <code>BotUser</code>
def initialize
+ @everyone = Auth::defaultbotuser
+ @botowner = Auth::botowner
bot_associate(nil)
end
@@ -494,7 +543,9 @@ module Irc def reset_hashes
@botusers = Hash.new
@allbotusers = Hash.new
- [Auth::anonbotuser, Auth::botowner].each { |x| @allbotusers[x.username.to_sym] = x }
+ [everyone, botowner].each { |x|
+ @allbotusers[x.username.to_sym] = x
+ }
end
# load botlist from userfile
@@ -524,7 +575,8 @@ module Irc # Maps <code>Irc::User</code> to BotUser
def irc_to_botuser(ircuser)
Irc::error_if_not_user(ircuser)
- return @botusers[ircuser] || Auth::anonbotuser
+ # TODO check netmasks
+ return @botusers[ircuser] || everyone
end
# creates a new BotUser
@@ -569,8 +621,8 @@ module Irc # is returned:
# * associated BotUser on _chan_
# * associated BotUser on all channels
- # * anonbotuser on _chan_
- # * anonbotuser on all channels
+ # * everyone on _chan_
+ # * everyone on all channels
#
def permit?(user, cmdtxt, chan=nil)
botuser = irc_to_botuser(user)
@@ -590,10 +642,10 @@ module Irc allow = botuser.permit?(cmd)
return allow unless allow.nil?
- unless botuser == Auth::anonbotuser
- allow = Auth::anonbotuser.permit?(cmd, chan) if chan
+ unless botuser == everyone
+ allow = everyone.permit?(cmd, chan) if chan
return allow unless allow.nil?
- allow = Auth::anonbotuser.permit?(cmd)
+ allow = everyone.permit?(cmd)
return allow unless allow.nil?
end
diff --git a/lib/rbot/config.rb b/lib/rbot/config.rb index ab16c442..f91cfa70 100644 --- a/lib/rbot/config.rb +++ b/lib/rbot/config.rb @@ -352,6 +352,9 @@ module Irc # bot:: parent bot class # create a new config hash from #{botclass}/conf.rbot + # TODO make this into a core module to guide a BotCOnfigManagerClass + # singleton instance from IRC + # def initialize(bot) @@bot = bot @@ -363,24 +366,24 @@ module Irc # unset # desc # and for arrays: - # add TODO - # remove TODO + # add + # remove @handler = MessageMapper.new(self) - @handler.map 'config list :module', :action => 'handle_list', + @handler.map 'config', 'config list :module', :action => 'handle_list', :defaults => {:module => false} - @handler.map 'config get :key', :action => 'handle_get' - @handler.map 'config desc :key', :action => 'handle_desc' - @handler.map 'config describe :key', :action => 'handle_desc' - @handler.map 'config set :key *value', :action => 'handle_set' - @handler.map 'config add :value to :key', :action => 'handle_add' - @handler.map 'config rm :value from :key', :action => 'handle_rm' - @handler.map 'config del :value from :key', :action => 'handle_rm' - @handler.map 'config delete :value from :key', :action => 'handle_rm' - @handler.map 'config unset :key', :action => 'handle_unset' - @handler.map 'config reset :key', :action => 'handle_unset' - @handler.map 'config help :topic', :action => 'handle_help', + @handler.map 'config', 'config get :key', :action => 'handle_get' + @handler.map 'config', 'config desc :key', :action => 'handle_desc' + @handler.map 'config', 'config describe :key', :action => 'handle_desc' + @handler.map 'config', 'config set :key *value', :action => 'handle_set' + @handler.map 'config', 'config add :value to :key', :action => 'handle_add' + @handler.map 'config', 'config rm :value from :key', :action => 'handle_rm' + @handler.map 'config', 'config del :value from :key', :action => 'handle_rm' + @handler.map 'config', 'config delete :value from :key', :action => 'handle_rm' + @handler.map 'config', 'config unset :key', :action => 'handle_unset' + @handler.map 'config', 'config reset :key', :action => 'handle_unset' + @handler.map 'config', 'config help :topic', :action => 'handle_help', :defaults => {:topic => false} - @handler.map 'help config :topic', :action => 'handle_help', + @handler.map 'config', 'help config :topic', :action => 'handle_help', :defaults => {:topic => false} if(File.exist?("#{@@bot.botclass}/conf.yaml")) diff --git a/lib/rbot/core/core.rb b/lib/rbot/core/core.rb index fcf5ac3a..55da1a7d 100644 --- a/lib/rbot/core/core.rb +++ b/lib/rbot/core/core.rb @@ -165,77 +165,78 @@ core = Core.new core.map "quit *msg",
:action => 'bot_quit',
:defaults => { :msg => nil },
- :auth => 'core::quit::quit'
+ :auth_path => 'quit'
core.map "restart *msg",
:action => 'bot_restart',
:defaults => { :msg => nil },
- :auth => 'core::quit::restart'
+ :auth_path => 'quit'
core.map "save",
:action => 'bot_save',
- :auth => 'core::config::save'
+ :auth_path => 'config'
core.map "rescan",
:action => 'bot_rescan',
- :auth => 'core::config::rescan'
+ :auth_path => 'config'
core.map "nick :nick",
:action => 'bot_nick',
- :auth => 'core::config::nick'
+ :auth_path => 'config'
core.map "status",
:action => 'bot_status',
- :auth => 'core::config::show::status'
+ :auth_path => 'config::show'
# TODO see above
#
# core.map "registry stats",
# :action => 'bot_reg_stat',
- # :auth => 'core::config::show::registry'
+ # :auth_path => 'config::show'
core.map "version",
:action => 'bot_version',
- :auth => 'core::config::show::version'
+ :auth_path => 'config::show'
core.map "quiet",
:action => 'bot_quiet',
- :auth => 'core::talk::quiet'
+ :auth_path => 'talk::set'
core.map "quiet in :chan",
:action => 'bot_quiet',
- :auth => 'core::talk::quiet'
+ :auth_path => 'talk::set'
core.map "talk",
:action => 'bot_talk',
- :auth => 'core::talk::talk'
+ :auth_path => 'talk::set'
core.map "quiet in :chan",
:action => 'bot_quiet',
- :auth => 'core::talk::talk'
+ :auth_path => 'talk::set'
+
+core.map "say :where *what",
+ :action => 'bot_say',
+ :auth_path => 'talk::do'
+core.map "action :where *what",
+ :action => 'bot_action',
+ :auth_path => 'talk::do'
+core.map "mode :where :what *who",
+ :action => 'bot_mode',
+ :auth_path => 'talk::do'
core.map "join :chan :pass",
:action => 'bot_join',
:defaults => {:pass => nil},
- :auth => 'core::movearound::join'
+ :auth_path => 'move'
core.map "part :chan",
:action => 'bot_part',
:defaults => {:chan => nil},
- :auth => 'core::movearound::part'
+ :auth_path => 'move'
core.map "hide",
:action => 'bot_hide',
- :auth => 'core::movearound::hide'
-
-core.map "say :where *what",
- :action => 'bot_say',
- :auth => 'core::talk::say'
-core.map "action :where *what",
- :action => 'bot_action',
- :auth => 'core::talk::act'
-core.map "mode :where :what *who",
- :action => 'bot_mode',
- :auth => 'core::talk::mode'
+ :auth_path => 'move'
core.map "ping",
- :action => 'bot_ping'
+ :action => 'bot_ping',
+ :auth_path => '!ping!'
core.map "help *topic",
:action => 'bot_help',
- :default => { :topic => [""] }
+ :default => { :topic => [""] },
+ :auth_path => '!help!'
# TODO the first line should probably go to the auth module?
#
-core.default_auth('*', true)
-core.default_auth('core', false)
-core.default_auth('core::config::show', true)
+core.default_auth('*', false)
+core.default_auth('config::show', true)
diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb index f1d9e127..d96e0368 100644 --- a/lib/rbot/ircbot.rb +++ b/lib/rbot/ircbot.rb @@ -346,6 +346,7 @@ class IrcBot log_session_end exit 2 end + @auth.everyone.set_default_permission("*", true) Dir.mkdir("#{botclass}/plugins") unless File.exist?("#{botclass}/plugins") @plugins = Plugins::pluginmanager diff --git a/lib/rbot/messagemapper.rb b/lib/rbot/messagemapper.rb index 200c676d..e4ad60b0 100644 --- a/lib/rbot/messagemapper.rb +++ b/lib/rbot/messagemapper.rb @@ -93,13 +93,14 @@ module Irc # :requirements => {:limit => /^\d+$/}, # :private => false # - def map(*args) - @templates << Template.new(*args) + def map(botmodule, *args) + @templates << Template.new(botmodule, *args) end def each @templates.each {|tmpl| yield tmpl} end + def last @templates.last end @@ -125,7 +126,7 @@ module Irc failures << [tmpl, "class does not respond to action #{action}"] next end - auth = tmpl.options[:auth] ? tmpl.options[:auth] : tmpl.items[0] + auth = tmpl.options[:full_auth_path] debug "checking auth for #{auth}" if m.bot.auth.allow?(auth, m.source, m.replyto) debug "template match found and auth'd: #{action.inspect} #{options.inspect}" @@ -157,13 +158,48 @@ module Irc attr_reader :defaults # The defaults hash attr_reader :options # The options hash attr_reader :items - def initialize(template, hash={}) - raise ArgumentError, "Second argument must be a hash!" unless hash.kind_of?(Hash) + + def initialize(botmodule, template, hash={}) + raise ArgumentError, "Third argument must be a hash!" unless hash.kind_of?(Hash) @defaults = hash[:defaults].kind_of?(Hash) ? hash.delete(:defaults) : {} @requirements = hash[:requirements].kind_of?(Hash) ? hash.delete(:requirements) : {} self.items = template + if hash.has_key?(:auth) + warning "Command #{template} in #{botmodule} uses old :auth syntax, please upgrade" + end + if hash.has_key?(:full_auth_path) + warning "Command #{template} in #{botmodule} sets :full_auth_path, please don't do this" + else + case botmodule + when String + pre = botmodule + when Plugins::BotModule + pre = botmodule.name + else + raise ArgumentError, "Can't find auth base in #{botmodule.inspect}" + end + post = items.reject{ |x| + x == pre || x.kind_of?(Symbol) + } + if post.empty? + post = nil + else + post = post.first + end + if hash.has_key?(:auth_path) + extra = hash[:auth_path] + pre = nil if extra.sub!(/^!/, "") + post = nil if extra.sub!(/!$/, "") + else + extra = nil + end + hash[:full_auth_path] = [pre,extra,post].compact.join("::") + # TODO check if the full_auth_path is sane + end + @options = hash end + def items=(str) items = str.split(/\s+/).collect {|c| (/^(:|\*)(\w+)$/ =~ c) ? (($1 == ':' ) ? $2.intern : "*#{$2}".intern) : c} if str.kind_of?(String) # split and convert ':xyz' to symbols items.shift if items.first == "" diff --git a/lib/rbot/plugins.rb b/lib/rbot/plugins.rb index 31fb1134..7e98b1b3 100644 --- a/lib/rbot/plugins.rb +++ b/lib/rbot/plugins.rb @@ -112,7 +112,7 @@ module Plugins @handler = MessageMapper.new(self) @registry = BotRegistryAccessor.new(@bot, self.class.to_s.gsub(/^.*::/, "")) - @manager.add_botmodule(kl, self) + @manager.add_botmodule(self) end def flush_registry @@ -130,10 +130,11 @@ module Plugins end def map(*args) - @handler.map(*args) + @handler.map(self, *args) # register this map name = @handler.last.items[0] - self.register name + auth = @handler.last.options[:full_auth_path] + self.register name, :auth => auth unless self.respond_to?('privmsg') def self.privmsg(m) handle(m) @@ -142,10 +143,10 @@ module Plugins end def map!(*args) - @handler.map(*args) + @handler.map(self, *args) # register this map name = @handler.last.items[0] - self.register name, {:hidden => true} + self.register name, :auth => auth, :hidden => true unless self.respond_to?('privmsg') def self.privmsg(m) handle(m) @@ -153,12 +154,23 @@ module Plugins end end - # Sets the default auth for command _cmd_ to _val_ on channel _chan_: - # usually _chan_ is either "*" for everywhere, public and private (in - # which case it can be omitted) or "?" for private communications + # Sets the default auth for command path _cmd_ to _val_ on channel _chan_: + # usually _chan_ is either "*" for everywhere, public and private (in which + # case it can be omitted) or "?" for private communications # def default_auth(cmd, val, chan="*") - Auth::anonbotuser.set_permission(cmd, val) + case cmd + when "*", "" + c = nil + else + c = cmd + end + Auth::defaultbotuser.set_default_permission(propose_default_path(c), val) + end + + # Gets the default command path which would be given to command _cmd_ + def propose_default_path(cmd) + [name, cmd].compact.join("::") end # return an identifier for this plugin, defaults to a list of the message @@ -184,11 +196,15 @@ module Plugins # register the plugin as a handler for messages prefixed +name+ # this can be called multiple times for a plugin to handle multiple # message prefixes - def register(name, opts={}) + def register(cmd, opts={}) raise ArgumentError, "Second argument must be a hash!" unless opts.kind_of?(Hash) - return if @manager.knows?(name, @botmodule_class) - @manager.register(name, @botmodule_class, self) - @botmodule_triggers << name unless opts.fetch(:hidden, false) + return if @manager.knows?(cmd, @botmodule_class) + if opts.has_key?(:auth) + @manager.register(self, cmd, opts[:auth]) + else + @manager.register(self, cmd, propose_default_path(cmd)) + end + @botmodule_triggers << cmd unless opts.fetch(:hidden, false) end # default usage method provided as a utility for simple plugins. The @@ -249,14 +265,16 @@ module Plugins return @commandmappers[kl.to_sym].has_key?(name.to_sym) end - # Returns +true+ if _name_ is a known botmodule of class kl - def register(name, kl, botmodule) - raise TypeError, "Third argument #{botmodule.inspect} is not of class BotModule" unless botmodule.class <= BotModule - @commandmappers[kl.to_sym][name.to_sym] = botmodule + # Registers botmodule _botmodule_ with command _cmd_ and command path _auth_path_ + def register(botmodule, cmd, auth_path) + raise TypeError, "First argument #{botmodule.inspect} is not of class BotModule" unless botmodule.class <= BotModule + kl = botmodule.botmodule_class + @commandmappers[kl.to_sym][cmd.to_sym] = {:botmodule => botmodule, :auth => auth_path} end - def add_botmodule(kl, botmodule) - raise TypeError, "Second argument #{botmodule.inspect} is not of class BotModule" unless botmodule.class <= BotModule + def add_botmodule(botmodule) + raise TypeError, "Argument #{botmodule.inspect} is not of class BotModule" unless botmodule.class <= BotModule + kl = botmodule.botmodule_class raise "#{kl.to_s} #{botmodule.name} already registered!" if @botmodules[kl.to_sym].include?(botmodule) @botmodules[kl.to_sym] << botmodule end @@ -488,11 +506,12 @@ module Plugins # TODO should also check core_module and plugins [core_commands, plugin_commands].each { |pl| if(pl.has_key?(key)) + p = pl[key][:botmodule] begin - return pl[key].help(key, params) + return p.help(key, params) rescue Exception => err #rescue TimeoutError, StandardError, NameError, SyntaxError => err - error report_error("#{p.botmodule_class} #{plugins[key].name} help() failed:", err) + error report_error("#{p.botmodule_class} #{p.name} help() failed:", err) end else return false @@ -532,14 +551,16 @@ module Plugins # FIXME use fetch? k = m.plugin.to_sym if pl.has_key?(k) - p = pl[k] + p = pl[k][:botmodule] + a = pl[k][:auth] else p = nil + a = nil end if p # TODO This should probably be checked elsewhere debug "Checking auth ..." - if @bot.auth.allow?(m.plugin, m.source, m.replyto) + if @bot.auth.allow?(a, m.source, m.replyto) debug "Checking response ..." if p.respond_to?("privmsg") begin @@ -558,9 +579,9 @@ module Plugins debug "#{p.botmodule_class} #{p.name} is registered, but #{m.source} isn't allowed to use #{m.plugin} on #{m.replyto}" end else - debug "No #{pl.values.first.botmodule_class} registered #{m.plugin}" unless pl.empty? + debug "No #{pl.values.first[:botmodule].botmodule_class} registered #{m.plugin}" unless pl.empty? end - debug "Finished delegating privmsg with key #{m.plugin}" + ( pl.empty? ? "" : " to #{pl.values.first.botmodule_class}s" ) + debug "Finished delegating privmsg with key #{m.plugin}" + ( pl.empty? ? "" : " to #{pl.values.first[:botmodule].botmodule_class}s" ) } return false rescue Exception => e |