X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=lib%2Frbot%2Fcore%2Fauth.rb;h=ce21ccc91c8633996345d32357fb48f59b0a4e65;hb=acc946be5b8d9042fb2a9263ba11d5ded2a509bb;hp=1066ecc8c3da594012110f1ccf49c8ab0a507cc9;hpb=918e880ead15058a5a8af1f99a2840985a051e7f;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/lib/rbot/core/auth.rb b/lib/rbot/core/auth.rb index 1066ecc8..ce21ccc9 100644 --- a/lib/rbot/core/auth.rb +++ b/lib/rbot/core/auth.rb @@ -4,8 +4,6 @@ # :title: rbot auth management from IRC # # Author:: Giuseppe "Oblomov" Bilotta -# Copyright:: (C) 2006,2007 Giuseppe Bilotta -# License:: GPL v2 class AuthModule < CoreBotModule @@ -39,6 +37,13 @@ class AuthModule < CoreBotModule def load_array(key=:default, forced=false) debug "loading botusers (#{key}): #{@registry[key].pretty_inspect}" @bot.auth.load_array(@registry[key], forced) if @registry.has_key?(key) + if @bot.auth.botowner.password != @bot.config['auth.password'] + error "Master password is out of sync!" + debug " db password: #{@bot.auth.botowner.password}" + debug "conf password: #{@bot.config['auth.password']}" + error "Using conf password" + @bot.auth.botowner.password = @bot.config['auth.password'] + end end # The permission parameters accept arguments with the following syntax: @@ -155,7 +160,7 @@ class AuthModule < CoreBotModule def auth_view_perm(m, params) begin if params[:user].nil? - user = get_botusername_for(m.source) + user = get_botuser_for(m.source) return m.reply(_("you are owner, you can do anything")) if user.owner? else user = @bot.auth.get_botuser(params[:user].sub(/^all$/,"everyone")) @@ -170,11 +175,11 @@ class AuthModule < CoreBotModule next if val.perm.empty? case k when :* - str << _("on any channel: ") + str << _("on any channel: ").dup when :"?" - str << _("in private: ") + str << _("in private: ").dup else - str << _("on #{k}: ") + str << _("on #{k}: ").dup end sub = [] val.perm.each { |cmd, bool| @@ -209,6 +214,86 @@ class AuthModule < CoreBotModule } end + def find_auth(pseudo) + k = pseudo.plugin.intern + cmds = @bot.plugins.commands + auth = nil + if cmds.has_key?(k) + cmds[k][:botmodule].handler.each do |tmpl| + options = tmpl.recognize(pseudo) + next if options.kind_of? MessageMapper::Failure + auth = tmpl.options[:full_auth_path] + break + end + end + return auth + end + + def auth_allow_deny(m, p) + begin + botuser = @bot.auth.get_botuser(p[:user].sub(/^all$/,"everyone")) + rescue + return m.reply(_("couldn't find botuser %{name}") % {:name => p[:user]}) + end + + if p[:where].to_s.empty? + where = :* + else + where = m.parse_channel_list(p[:where].to_s).first # should only be one anyway + end + + if p.has_key? :auth_path + auth_path = p[:auth_path] + else + # pseudo-message to find the template. The source is ignored, and the + # target is set according to where the template should be checked + # (public or private) + # This might still fail in the case of 'everywhere' for commands there are + # really only private + case where + when :"?" + pseudo_target = @bot.myself + when :* + pseudo_target = m.channel + else + pseudo_target = m.server.channel(where) + end + + pseudo = PrivMessage.new(bot, m.server, m.source, pseudo_target, p[:stuff].to_s) + + auth_path = find_auth(pseudo) + end + debug auth_path + + if auth_path + allow = p[:allow] + if @bot.auth.permit?(botuser, auth_path, where) + return m.reply(_("%{user} can already do that") % {:user => botuser}) if allow + else + return m.reply(_("%{user} can't do that already") % {:user => botuser}) if !allow + end + cmd = PrivMessage.new(bot, m.server, m.source, m.target, "permissions set %{sign}%{path} %{where} for %{user}" % { + :path => auth_path, + :user => p[:user], + :sign => (allow ? '+' : '-'), + :where => p[:where].to_s + }) + handle(cmd) + else + m.reply(_("sorry, %{cmd} doesn't look like a valid command. maybe you misspelled it, or you need to specify it should be in private?") % { + :cmd => p[:stuff].to_s + }) + end + end + + def auth_allow(m, p) + auth_allow_deny(m, p.merge(:allow => true)) + end + + def auth_deny(m, p) + auth_allow_deny(m, p.merge(:allow => false)) + end + def get_botuser_for(user) @bot.auth.irc_to_botuser(user) end @@ -217,8 +302,8 @@ class AuthModule < CoreBotModule get_botuser_for(user).username end - def welcome(user) - _("welcome, %{user}") % {:user => get_botusername_for(user)} + def say_welcome(m) + m.reply _("welcome, %{user}") % {:user => get_botusername_for(m.source)} end def auth_auth(m, params) @@ -230,7 +315,7 @@ class AuthModule < CoreBotModule begin case @bot.auth.login(m.source, params[:botuser], params[:password]) when true - m.reply welcome(m.source) + say_welcome(m) @bot.auth.set_changed else m.reply _("sorry, can't do") @@ -246,7 +331,7 @@ class AuthModule < CoreBotModule if u.default? m.reply _("I couldn't find anything to let you login automatically") else - m.reply welcome(m.source) + say_welcome(m) end end @@ -316,17 +401,37 @@ class AuthModule < CoreBotModule return _("user list : lists all the botusers") when "destroy" return _("user destroy : destroys . This function %{highlight}must%{highlight} be called in two steps. On the first call is queued for destruction. On the second call, which must be in the form 'user confirm destroy ', the botuser will be destroyed. If you want to cancel the destruction, issue the command 'user cancel destroy '") % {:highlight => Bold} + when "export" + return _("user export [to ]: exports user data to file (default: new-auth.users)") + when "import" + return _("user import [from ]: import user data from file (default: new-auth.users)") else - return _("user topics: show, enable|disable, add|rm netmask, set, reset, tell, create, list, destroy") + return _("user topics: show, enable|disable, add|rm netmask, set, reset, tell, create, list, destroy, import, export") end when "auth" - return _("auth : log in as the bot owner; other commands: login, whoami, permission syntax, permissions [re]set, permissions view, user, meet, hello") + return _("auth : log in as the bot owner; other commands: login, whoami, permissions syntax, permissions [re]set, permissions view, user, meet, hello, allow, deny") when "meet" return _("meet [as ]: creates a bot user for nick, calling it user (defaults to the nick itself)") when "hello" return _("hello: creates a bot user for the person issuing the command") + when "allow" + return [ + _("allow to do []: gives botuser the permissions to execute a command such as the provided sample command"), + _("(in private or in channel, according to the optional )."), + _(" should be a full command, not just the command keyword --"), + _("correct: allow user to do addquote stuff --"), + _("wrong: allow user to do addquote.") + ].join(" ") + when "deny" + return [ + _("deny from doing []: removes from botuser the permissions to execute a command such as the provided sample command"), + _("(in private or in channel, according to the optional )."), + _(" should be a full command, not just the command keyword --"), + _("correct: deny user from doing addquote stuff --"), + _("wrong: deny user from doing addquote.") + ].join(" ") else - return _("auth commands: auth, login, whoami, who, permission[s], user, meet, hello") + return _("auth commands: auth, login, whoami, who, permission[s], user, meet, hello, allow, deny") end end @@ -544,7 +649,7 @@ class AuthModule < CoreBotModule if !nick # we are actually responding to a 'hello' command unless m.botuser.transient? - m.reply @bot.lang.get('hello_X') % m.botuser + m.reply @bot.lang.get('hello_X') % m.botuser, :nick => false return end nick = m.sourcenick @@ -563,7 +668,7 @@ class AuthModule < CoreBotModule met = @bot.auth.make_permanent(irc_user, buname) @bot.auth.set_changed call_event(:botuser,:post_perm, {:irc_user => irc_user, :bot_user => buname}) - m.reply @bot.lang.get('hello_X') % met + m.reply @bot.lang.get('hello_X') % met, :nick => false @bot.say nick, _("you are now registered as %{buname}. I created a random password for you : %{pass} and you can change it at any time by telling me 'user set password ' in private" % { :buname => buname, :pass => met.password @@ -584,7 +689,7 @@ class AuthModule < CoreBotModule rescue return m.reply(_("couldn't find botuser %{user}") % {:user => params[:botuser]}) end - m.reply(_("I'm not telling the master password to anyway, pal")) if botuser == @bot.auth.botowner + return m.reply(_("I'm not telling the master password to anyone, pal")) if botuser == @bot.auth.botowner msg = _("the password for botuser %{user} is %{password}") % {:user => botuser.username, :password => botuser.password} @bot.say user, msg @@ -608,7 +713,7 @@ class AuthModule < CoreBotModule def auth_list_users(m, params) # TODO name regexp to filter results - list = @bot.auth.save_array.inject([]) { |list, x| ['everyone', 'owner'].include?(x[:username]) ? list : list << x[:username] } + list = @bot.auth.save_array.inject([]) { |lst, x| ['everyone', 'owner'].include?(x[:username]) ? lst : lst << x[:username] } if defined?(@destroy_q) list.map! { |x| @destroy_q.include?(x) ? x + _(" (queued for destruction)") : x @@ -624,7 +729,7 @@ class AuthModule < CoreBotModule buname = params[:name] return m.reply(_("You can't destroy %{user}") % {:user => buname}) if ["everyone", "owner"].include?(buname) - mod = params[:modifier].to_sym rescue nil + mod = params[:modifier].nil_or_empty? ? nil : params[:modifier].to_sym buser_array = @bot.auth.save_array buser_hash = buser_array.inject({}) { |h, u| @@ -716,13 +821,13 @@ class AuthModule < CoreBotModule def auth_export(m, params) - exportfile = "#{@bot.botclass}/new-auth.users" + exportfile = @bot.path "new-auth.users" what = params[:things] has_to = what[-2] == "to" if has_to - exportfile = "#{@bot.botclass}/#{what[-1]}" + exportfile = @bot.path what[-1] what.slice!(-2,2) end @@ -788,13 +893,13 @@ class AuthModule < CoreBotModule def auth_import(m, params) - importfile = "#{@bot.botclass}/new-auth.users" + importfile = @bot.path "new-auth.users" what = params[:things] has_from = what[-2] == "from" if has_from - importfile = "#{@bot.botclass}/#{what[-1]}" + importfile = @bot.path what[-1] what.slice!(-2,2) end @@ -918,6 +1023,16 @@ auth.map "user list", auth.map "user *data", :action => 'auth_manage_user' +auth.map "allow :user to do *stuff [*where]", + :action => 'auth_allow', + :requirements => {:where => /^(?:anywhere|everywhere|[io]n \S+)$/}, + :auth_path => ':edit::other:' + +auth.map "deny :user from doing *stuff [*where]", + :action => 'auth_deny', + :requirements => {:where => /^(?:anywhere|everywhere|[io]n \S+)$/}, + :auth_path => ':edit::other:' + auth.default_auth("user", true) auth.default_auth("edit::other", false)