X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=lib%2Frbot%2Fcore%2Fauth.rb;h=eee500456c241e135fb919018c572d98bc359cd8;hb=12906a51f698aebe1c9a5e19b15555ebbbcc4368;hp=82b784e3013b7429c1eb6760276f9c0c776a1828;hpb=30dab5b566a68b48b22bbfd949f1ab3ffcb531b0;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/lib/rbot/core/auth.rb b/lib/rbot/core/auth.rb index 82b784e3..eee50045 100644 --- a/lib/rbot/core/auth.rb +++ b/lib/rbot/core/auth.rb @@ -1,26 +1,18 @@ #-- vim:sw=2:et #++ -# TODO: -# * user destroy: should work in two phases: -# * user destroy _botuser_ would queue _botuser_ for -# destruction -# * user destroy _botuser_ _password_ would actually destroy -# _botuser_ if it was queued and the _password_ is correct -# * user copy -# * user rename # -# It should be fairly easy to implement all of this stuff by using -# @bot.auth.load_array and @bot.auth.save_array: this means it can be tested -# live and without any need to touch the rbot kernel file +botuser.rb+ +# :title: rbot auth management from IRC # - +# Author:: Giuseppe "Oblomov" Bilotta +# Copyright:: (C) 2006,2007 Giuseppe Bilotta +# License:: GPL v2 class AuthModule < CoreBotModule def initialize super load_array(:default, true) - debug "Initialized auth. Botusers: #{@bot.auth.save_array.inspect}" + debug "initialized auth. Botusers: #{@bot.auth.save_array.inspect}" end def save @@ -67,9 +59,9 @@ class AuthModule < CoreBotModule next end if "+-".include?(x[0]) - warns << ArgumentError("please do not use + or - in front of command #{x} when resetting") unless setting + warns << ArgumentError.new("please do not use + or - in front of command #{x} when resetting") unless setting else - warns << ArgumentError("+ or - expected in front of #{x}") if setting + warns << ArgumentError.new("+ or - expected in front of #{x}") if setting end cmds << x else # parse locations @@ -85,30 +77,41 @@ class AuthModule < CoreBotModule warns << ArgumentError("#{x} doesn't look like a channel name") unless @bot.server.supports[:chantypes].include?(x[0]) locs << x end - unless wants_more + unless want_more last_idx = i break end end } - warns << "trailing comma" if wants_more + warns << "trailing comma" if want_more warns << "you probably forgot a comma" unless last_idx == ar.length - 1 return cmds, locs, warns end - def auth_set(m, params) - cmds, locs, warns = parse_args(params[:args]) + def auth_edit_perm(m, params) + + setting = m.message.split[1] == "set" + splits = params[:args] + + has_for = splits[-2] == "for" + return usage(m) unless has_for + + begin + user = @bot.auth.get_botuser(splits[-1].sub(/^all$/,"everyone")) + rescue + return m.reply("couldn't find botuser #{splits[-1]}") + end + return m.reply("you can't change permissions for #{user.username}") if user == @bot.auth.botowner + splits.slice!(-2,2) if has_for + + cmds, locs, warns = parse_args(splits, setting) errs = warns.select { |w| w.kind_of?(Exception) } + unless errs.empty? m.reply "couldn't satisfy your request: #{errs.join(',')}" return end - user = params[:user].sub(/^all$/,"everyone") - begin - bu = @bot.auth.get_botuser(user) - rescue - return m.reply "couldn't find botuser #{user}" - end + if locs.empty? locs << "*" end @@ -121,18 +124,61 @@ class AuthModule < CoreBotModule ch = m.target.to_s if loc == "_" end cmds.each { |setval| - val = setval[0].chr == '+' - cmd = setval[1..-1] - bu.set_permission(cmd, val, ch) + if setting + val = setval[0].chr == '+' + cmd = setval[1..-1] + user.set_permission(cmd, val, ch) + else + cmd = setval + user.reset_permission(cmd, ch) + end } } rescue => e - m.reply "Something went wrong while trying to set the permissions" + m.reply "something went wrong while trying to set the permissions" raise end @bot.auth.set_changed - debug "User #{user} permissions changed" - m.reply "Ok, #{user} now also has permissions #{params[:args].join(' ')}" + debug "user #{user} permissions changed" + m.okay + end + + def auth_view_perm(m, params) + begin + if params[:user].nil? + user = get_botusername_for(m.source) + return m.reply("you are owner, you can do anything") if user == @bot.auth.botwoner + else + user = @bot.auth.get_botuser(params[:user].sub(/^all$/,"everyone")) + return m.reply("owner can do anything") if user.username == "owner" + end + rescue + return m.reply("couldn't find botuser #{params[:user]}") + end + perm = user.perm + str = [] + perm.each { |k, val| + next if val.perm.empty? + case k + when :* + str << "on any channel: " + when :"?" + str << "in private: " + else + str << "on #{k}: " + end + sub = [] + val.perm.each { |cmd, bool| + sub << (bool ? "+" : "-") + sub.last << cmd.to_s + } + str.last << sub.join(', ') + } + if str.empty? + m.reply "no permissions set for #{user.username}" + else + m.reply "permissions for #{user.username}:: #{str.join('; ')}" + end end def get_botuser_for(user) @@ -147,6 +193,11 @@ class AuthModule < CoreBotModule "welcome, #{get_botusername_for(user)}" end + def auth_auth(m, params) + params[:botuser] = 'owner' + auth_login(m,params) + end + def auth_login(m, params) begin case @bot.auth.login(m.source, params[:botuser], params[:password]) @@ -186,38 +237,48 @@ class AuthModule < CoreBotModule m.reply rep end - def help(plugin, topic="") - case topic - when /^login/ - return "login [] []: logs in to the bot as botuser with password . can be omitted if allows login-by-mask and your netmask is among the known ones. if is omitted too autologin will be attempted" - when /^whoami/ + def help(cmd, topic="") + case cmd + when "login" + return "login [] []: logs in to the bot as botuser with password . When using the full form, you must contact the bot in private. can be omitted if allows login-by-mask and your netmask is among the known ones. if is omitted too autologin will be attempted" + when "whoami" return "whoami: names the botuser you're linked to" - when /^permission syntax/ - return "A permission is specified as module::path::to::cmd; when you want to enable it, prefix it with +; when you want to disable it, prefix it with -; when using the +reset+ command, do not use any prefix" when /^permission/ - return "permissions (re)set [in ] for : sets or resets the permissions for botuser in channel (use ? to change the permissions for private addressing)" - when /^user show/ - return "user show : shows info about the user; can be any of autologin, login-by-mask, netmasks" - when /^user (en|dis)able/ - return "user enable|disable : turns on or off (autologin, login-by-mask)" - when /^user set/ - return "user set password : sets the user password to ; passwords can only contain upper and lowercase letters and numbers, and must be at least 4 characters long" - when /^user (add|rm)/ - return "user add|rm netmask : adds/removes netmask from the list of netmasks known to the botuser you're linked to" - when /^user reset/ - return "user reset : resets to the default values. can be +netmasks+ (the list will be emptied), +autologin+ or +login-by-mask+ (will be reset to the default value) or +password+ (a new one will be generated and you'll be told in private)" - when /^user tell/ - return "user tell the password for : contacts in private to tell him/her the password for " - when /^user create/ - return "user create : create botuser named with password . The password can be omitted, in which case a random one will be generated. The should only contain alphanumeric characters and the underscore (_)" - when /^user list/ - return "user list : lists all the botusers" - when /^user destroy/ - return "user destroy : destroys ; this function #{Bold}must#{Bold} be called in two steps. On the first call, no password must be specified: is then queued for destruction. On the second call, you must specify the correct password for , and it will be destroyed. If you want to cancel the destruction, issue the command +user cancel destroy +" - when /^user/ - return "user show, enable|disable, add|rm netmask, set, reset, tell, create, list, destroy" + case topic + when "syntax" + return "a permission is specified as module::path::to::cmd; when you want to enable it, prefix it with +; when you want to disable it, prefix it with -; when using the +reset+ command, do not use any prefix" + when "set", "reset", "[re]set", "(re)set" + return "permissions [re]set [in ] for : sets or resets the permissions for botuser in channel (use ? to change the permissions for private addressing)" + when "view" + return "permissions view [for ]: display the permissions for user " + else + return "topics: syntax, (re)set, view" + end + when "user" + case topic + when "show" + return "user show : shows info about the user; can be any of autologin, login-by-mask, netmasks" + when /^(en|dis)able/ + return "user enable|disable : turns on or off (autologin, login-by-mask)" + when "set" + return "user set password : sets the user password to ; passwords can only contain upper and lowercase letters and numbers, and must be at least 4 characters long" + when "add", "rm" + return "user add|rm netmask : adds/removes netmask from the list of netmasks known to the botuser you're linked to" + when "reset" + return "user reset : resets to the default values. can be +netmasks+ (the list will be emptied), +autologin+ or +login-by-mask+ (will be reset to the default value) or +password+ (a new one will be generated and you'll be told in private)" + when "tell" + return "user tell the password for : contacts in private to tell him/her the password for " + when "create" + return "user create : create botuser named with password . The password can be omitted, in which case a random one will be generated. The should only contain alphanumeric characters and the underscore (_)" + when "list" + return "user list : lists all the botusers" + when "destroy" + return "user destroy : destroys ; this function #{Bold}must#{Bold} be called in two steps. On the first call, no password must be specified: is then queued for destruction. On the second call, you must specify the correct password for , and it will be destroyed. If you want to cancel the destruction, issue the command +user cancel destroy +" + else + return "user show, enable|disable, add|rm netmask, set, reset, tell, create, list, destroy" + end else - return "#{name}: login, whoami, permission syntax, permissions, user" + return "#{name}: login, whoami, permission syntax, permissions [re]set, permissions view, user" end end @@ -256,13 +317,14 @@ class AuthModule < CoreBotModule has_for = splits[-2] == "for" butarget = @bot.auth.get_botuser(splits[-1]) if has_for - return m.reply "you can't mess with #{butarget.username}" if butarget == @bot.auth.botowner && botuser != butarget + return m.reply("you can't mess with #{butarget.username}") if butarget == @bot.auth.botowner && botuser != butarget splits.slice!(-2,2) if has_for bools = [:autologin, :"login-by-mask"] can_set = [:password] can_addrm = [:netmasks] can_reset = bools + can_set + can_addrm + can_show = can_reset + ["perms"] case cmd.to_sym @@ -274,11 +336,11 @@ class AuthModule < CoreBotModule props = can_reset when "password" if botuser != butarget - return m.reply "no way I'm telling you the master password!" if butarget == @bot.auth.botowner - return m.reply "you can't ask for someone else's password" + return m.reply("no way I'm telling you the master password!") if butarget == @bot.auth.botowner + return m.reply("you can't ask for someone else's password") end - return m.reply "c'mon, you can't be asking me seriously to tell you the password in public!" if m.public? - return m.reply "the password for #{butarget.username} is #{butarget.password}" + return m.reply("c'mon, you can't be asking me seriously to tell you the password in public!") if m.public? + return m.reply("the password for #{butarget.username} is #{butarget.password}") else props = splits[1..-1] end @@ -302,13 +364,13 @@ class AuthModule < CoreBotModule end end } - return m.reply "#{butarget.username} #{str.join('; ')}" + return m.reply("#{butarget.username} #{str.join('; ')}") when :enable, :disable - return m.reply "you can't change the default user" if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::other::default") - return m.reply "you can't edit #{butarget.username}" if butarget != botuser and !botuser.permit?("auth::edit::other") + return m.reply("you can't change the default user") if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::other::default") + return m.reply("you can't edit #{butarget.username}") if butarget != botuser and !botuser.permit?("auth::edit::other") - return m.reply need_args(cmd) unless splits[1] + return m.reply(need_args(cmd)) unless splits[1] things = [] skipped = [] splits[1..-1].each { |a| @@ -326,30 +388,30 @@ class AuthModule < CoreBotModule m.reply "I haven't changed anything" else @bot.auth.set_changed - return auth_manage_user(m, {:data => ["show"] + things }) + return auth_manage_user(m, {:data => ["show"] + things + ["for", butarget.username] }) end when :set - return m.reply "you can't change the default user" if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::default") - return m.reply "you can't edit #{butarget.username}" if butarget != botuser and !botuser.permit?("auth::edit::other") + return m.reply("you can't change the default user") if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::default") + return m.reply("you can't edit #{butarget.username}") if butarget != botuser and !botuser.permit?("auth::edit::other") - return m.reply need_args(cmd) unless splits[1] + return m.reply(need_args(cmd)) unless splits[1] arg = splits[1].to_sym - return m.reply not_args(cmd, *can_set) unless can_set.include?(arg) + return m.reply(not_args(cmd, *can_set)) unless can_set.include?(arg) argarg = splits[2] - return m.reply need_args([cmd, splits[1]].join(" ")) unless argarg + return m.reply(need_args([cmd, splits[1]].join(" "))) unless argarg if arg == :password && m.public? - return m.reply "is that a joke? setting the password in public?" + return m.reply("is that a joke? setting the password in public?") end set_prop(butarget, arg, argarg) @bot.auth.set_changed - auth_manage_user(m, {:data => ["show", arg] }) + auth_manage_user(m, {:data => ["show", arg, "for", butarget.username] }) when :reset - return m.reply "you can't change the default user" if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::default") - return m.reply "you can't edit #{butarget.username}" if butarget != botuser and !botuser.permit?("auth::edit::other") + return m.reply("you can't change the default user") if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::default") + return m.reply("you can't edit #{butarget.username}") if butarget != botuser and !botuser.permit?("auth::edit::other") - return m.reply need_args(cmd) unless splits[1] + return m.reply(need_args(cmd)) unless splits[1] things = [] skipped = [] splits[1..-1].each { |a| @@ -368,16 +430,16 @@ class AuthModule < CoreBotModule else @bot.auth.set_changed @bot.say m.source, "the password for #{butarget.username} is now #{butarget.password}" if things.include?("password") - return auth_manage_user(m, {:data => ["show"] + things - ["password"]}) + return auth_manage_user(m, {:data => (["show"] + things - ["password"]) + ["for", butarget.username]}) end when :add, :rm, :remove, :del, :delete - return m.reply "you can't change the default user" if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::default") - return m.reply "you can't edit #{butarget.username}" if butarget != botuser and !botuser.permit?("auth::edit::other") + return m.reply("you can't change the default user") if butarget == @bot.auth.everyone and !botuser.permit?("auth::edit::default") + return m.reply("you can't edit #{butarget.username}") if butarget != botuser and !botuser.permit?("auth::edit::other") arg = splits[1] if arg.nil? or arg !~ /netmasks?/ or splits[2].nil? - return m.reply "I can only add/remove netmasks. See +help user add+ for more instructions" + return m.reply("I can only add/remove netmasks. See +help user add+ for more instructions") end method = cmd.to_sym == :add ? :add_netmask : :delete_netmask @@ -393,7 +455,7 @@ class AuthModule < CoreBotModule } m.reply "I failed to #{cmd} #{failed.join(', ')}" unless failed.empty? @bot.auth.set_changed - return auth_manage_user(m, {:data => ["show", "netmasks"] }) + return auth_manage_user(m, {:data => ["show", "netmasks", "for", butarget.username] }) else m.reply "sorry, I don't know how to #{m.message}" @@ -405,7 +467,7 @@ class AuthModule < CoreBotModule begin botuser = @bot.auth.get_botuser(params[:botuser]) rescue - return m.reply "coudln't find botuser #{params[:botuser]})" + return m.reply("coudln't find botuser #{params[:botuser]})") end m.reply "I'm not telling the master password to anyway, pal" if botuser == @bot.auth.botowner msg = "the password for botuser #{botuser.username} is #{botuser.password}" @@ -416,15 +478,16 @@ class AuthModule < CoreBotModule def auth_create_user(m, params) name = params[:name] password = params[:password] - return m.reply "are you nuts, creating a botuser with a publicly known password?" if m.public? and not password.nil? + return m.reply("are you nuts, creating a botuser with a publicly known password?") if m.public? and not password.nil? begin bu = @bot.auth.create_botuser(name, password) @bot.auth.set_changed rescue => e - return m.reply "Failed to create #{name}: #{e}" + m.reply "failed to create #{name}: #{e}" debug e.inspect + "\n" + e.backtrace.join("\n") + return end - m.reply "Created botuser #{bu.username}" + m.reply "created botuser #{bu.username}" end def auth_list_users(m, params) @@ -435,23 +498,24 @@ class AuthModule < CoreBotModule @destroy_q.include?(x) ? x + " (queued for destruction)" : x } end - return m.reply "I have no botusers other than the default ones" if list.empty? - return m.reply "Botuser#{'s' if list.length > 1}: #{list.join(', ')}" + return m.reply("I have no botusers other than the default ones") if list.empty? + return m.reply("botuser#{'s' if list.length > 1}: #{list.join(', ')}") end def auth_destroy_user(m, params) @destroy_q = [] unless defined?(@destroy_q) buname = params[:name] - returm m.reply "You can't destroy #{buname}" if ["everyone", "owner"].include?(buname) + return m.reply("You can't destroy #{buname}") if ["everyone", "owner"].include?(buname) cancel = m.message.split[1] == 'cancel' password = params[:password] + buser_array = @bot.auth.save_array buser_hash = buser_array.inject({}) { |h, u| h[u[:username]] = u h } - return m.reply "No such botuser #{buname}" unless buser_hash.keys.include?(buname) + return m.reply("no such botuser #{buname}") unless buser_hash.keys.include?(buname) if cancel if @destroy_q.include?(buname) @@ -470,52 +534,252 @@ class AuthModule < CoreBotModule @destroy_q << buname rep = "#{buname} queued for destruction" end - return m.reply rep + ", use #{Bold}user destroy #{buname} #{Bold} to destroy it" + return m.reply(rep + ", use #{Bold}user destroy #{buname} #{Bold} to destroy it") else begin - return m.reply "#{buname} is not queued for destruction yet" unless @destroy_q.include?(buname) - return m.reply "wrong password for #{buname}" unless buser_hash[buname][:password] == password + return m.reply("#{buname} is not queued for destruction yet") unless @destroy_q.include?(buname) + return m.reply("wrong password for #{buname}") unless buser_hash[buname][:password] == password buser_array.delete_if { |u| u[:username] == buname } @destroy_q.delete(buname) @bot.auth.load_array(buser_array, true) + @bot.auth.set_changed rescue => e - return m.reply "failed: #{e}" + return m.reply("failed: #{e}") + end + return m.reply("botuser #{buname} destroyed") + end + + end + + def auth_copy_ren_user(m, params) + source = Auth::BotUser.sanitize_username(params[:source]) + dest = Auth::BotUser.sanitize_username(params[:dest]) + return m.reply("please don't touch the default users") if (["everyone", "owner"] | [source, dest]).length < 4 + + buser_array = @bot.auth.save_array + buser_hash = buser_array.inject({}) { |h, u| + h[u[:username]] = u + h + } + + return m.reply("no such botuser #{source}") unless buser_hash.keys.include?(source) + return m.reply("botuser #{dest} exists already") if buser_hash.keys.include?(dest) + + copying = m.message.split[1] == "copy" + begin + if copying + h = {} + buser_hash[source].each { |k, val| + h[k] = val.dup + } + else + h = buser_hash[source] end - return m.reply "user #{buname} destroyed" + h[:username] = dest + buser_array << h if copying + + @bot.auth.load_array(buser_array, true) + @bot.auth.set_changed + rescue => e + return m.reply("failed: #{e}") end + return m.reply("botuser #{source} copied to #{dest}") if copying + return m.reply("botuser #{source} renamed to #{dest}") end + def auth_export(m, params) + + exportfile = "#{@bot.botclass}/new-auth.users" + + what = params[:things] + + has_to = what[-2] == "to" + if has_to + exportfile = "#{@bot.botclass}/#{what[-1]}" + what.slice!(-2,2) + end + + what.delete("all") + + m.reply "selecting data to export ..." + + buser_array = @bot.auth.save_array + buser_hash = buser_array.inject({}) { |h, u| + h[u[:username]] = u + h + } + + if what.empty? + we_want = buser_hash + else + we_want = buser_hash.delete_if { |key, val| + not what.include?(key) + } + end + + m.reply "preparing data for export ..." + begin + yaml_hash = {} + we_want.each { |k, val| + yaml_hash[k] = {} + val.each { |kk, v| + case kk + when :username + next + when :netmasks + yaml_hash[k][kk] = [] + v.each { |nm| + yaml_hash[k][kk] << { + :fullform => nm.fullform, + :casemap => nm.casemap.to_s + } + } + else + yaml_hash[k][kk] = v + end + } + } + rescue => e + m.reply "failed to prepare data: #{e}" + debug e.backtrace.dup.unshift(e.inspect).join("\n") + return + end + + m.reply "exporting to #{exportfile} ..." + begin + # m.reply yaml_hash.inspect + File.open(exportfile, "w") do |file| + file.puts YAML::dump(yaml_hash) + end + rescue => e + m.reply "failed to export users: #{e}" + debug e.backtrace.dup.unshift(e.inspect).join("\n") + return + end + m.reply "done" + end + + def auth_import(m, params) + + importfile = "#{@bot.botclass}/new-auth.users" + + what = params[:things] + + has_from = what[-2] == "from" + if has_from + importfile = "#{@bot.botclass}/#{what[-1]}" + what.slice!(-2,2) + end + + what.delete("all") + + m.reply "reading #{importfile} ..." + begin + yaml_hash = YAML::load_file(importfile) + rescue => e + m.reply "failed to import from: #{e}" + debug e.backtrace.dup.unshift(e.inspect).join("\n") + return + end + + # m.reply yaml_hash.inspect + + m.reply "selecting data to import ..." + + if what.empty? + we_want = yaml_hash + else + we_want = yaml_hash.delete_if { |key, val| + not what.include?(key) + } + end + + m.reply "parsing data from import ..." + + buser_hash = {} + + begin + yaml_hash.each { |k, val| + buser_hash[k] = { :username => k } + val.each { |kk, v| + case kk + when :netmasks + buser_hash[k][kk] = [] + v.each { |nm| + buser_hash[k][kk] << nm[:fullform].to_irc_netmask(:casemap => nm[:casemap].to_irc_casemap).to_irc_netmask(:server => @bot.server) + } + else + buser_hash[k][kk] = v + end + } + } + rescue => e + m.reply "failed to parse data: #{e}" + debug e.backtrace.dup.unshift(e.inspect).join("\n") + return + end + + # m.reply buser_hash.inspect + + org_buser_array = @bot.auth.save_array + org_buser_hash = org_buser_array.inject({}) { |h, u| + h[u[:username]] = u + h + } + + # TODO we may want to do a(n optional) key-by-key merge + # + org_buser_hash.merge!(buser_hash) + new_buser_array = org_buser_hash.values + @bot.auth.load_array(new_buser_array, true) + @bot.auth.set_changed + + m.reply "done" + end + end auth = AuthModule.new +auth.map "user export *things", + :action => 'auth_export', + :defaults => { :things => ['all'] }, + :auth_path => ':manage:fedex:' + +auth.map "user import *things", + :action => 'auth_import', + :auth_path => ':manage:fedex:' + auth.map "user create :name :password", :action => 'auth_create_user', :defaults => {:password => nil}, - :auth_path => 'user::manage::create!' + :auth_path => ':manage:' -auth.map "user cancel destroy :name :password", +auth.map "user [cancel] destroy :name :password", :action => 'auth_destroy_user', :defaults => { :password => nil }, - :auth_path => 'user::manage::destroy::cancel!' + :auth_path => ':manage::destroy:' -auth.map "user destroy :name :password", - :action => 'auth_destroy_user', - :defaults => { :password => nil }, - :auth_path => 'user::manage::destroy!' +auth.map "user copy :source [to] :dest", + :action => 'auth_copy_ren_user', + :auth_path => ':manage:' + +auth.map "user rename :source [to] :dest", + :action => 'auth_copy_ren_user', + :auth_path => ':manage:' auth.default_auth("user::manage", false) auth.map "user tell :user the password for :botuser", :action => 'auth_tell_password', - :auth_path => 'user::tell' + :auth_path => '::' auth.map "user list", :action => 'auth_list_users', - :auth_path => 'user::list!' + :auth_path => '::' auth.map "user *data", :action => 'auth_manage_user' @@ -527,6 +791,11 @@ auth.map "whoami", :action => 'auth_whoami', :auth_path => '!*!' +auth.map "auth :password", + :action => 'auth_auth', + :public => false, + :auth_path => '!login!' + auth.map "login :botuser :password", :action => 'auth_login', :public => false, @@ -541,13 +810,17 @@ auth.map "login", :action => 'auth_autologin', :auth_path => '!login!' -auth.map "permissions set *args for :user", - :action => 'auth_set', +auth.map "permissions set *args", + :action => 'auth_edit_perm', :auth_path => ':edit::set:' -auth.map "permissions reset *args for :user", - :action => 'auth_reset', +auth.map "permissions reset *args", + :action => 'auth_edit_perm', :auth_path => ':edit::reset:' +auth.map "permissions view [for :user]", + :action => 'auth_view_perm', + :auth_path => '::' + auth.default_auth('*', false)