| Class | AuthModule |
| In: |
lib/rbot/core/auth.rb
|
| Parent: | CoreBotModule |
| Author: | Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com> |
# File lib/rbot/core/auth.rb, line 10
10: def initialize
11: super
12:
13: # The namespace migration causes each Irc::Auth::PermissionSet to be
14: # unrecoverable, and we have to rename their class name to
15: # Irc::Bot::Auth::PermissionSet
16: @registry.recovery = Proc.new { |val|
17: patched = val.sub("o:\035Irc::Auth::PermissionSet", "o:\042Irc::Bot::Auth::PermissionSet")
18: Marshal.restore(patched)
19: }
20:
21: load_array(:default, true)
22: debug "initialized auth. Botusers: #{@bot.auth.save_array.pretty_inspect}"
23: end
# File lib/rbot/core/auth.rb, line 456
456: def ask_bool_prop(botuser, prop)
457: k = prop.to_s.gsub("-","_")
458: botuser.send( (k + "?").to_sym)
459: end
# File lib/rbot/core/auth.rb, line 289
289: def auth_allow(m, p)
290: auth_allow_deny(m, p.merge(:allow => true))
291: end
# File lib/rbot/core/auth.rb, line 232
232: def auth_allow_deny(m, p)
233: begin
234: botuser = @bot.auth.get_botuser(p[:user].sub(/^all$/,"everyone"))
235: rescue
236: return m.reply(_("couldn't find botuser %{name}") % {:name => p[:user]})
237: end
238:
239: if p[:where].to_s.empty?
240: where = :*
241: else
242: where = m.parse_channel_list(p[:where].to_s).first # should only be one anyway
243: end
244:
245: if p.has_key? :auth_path
246: auth_path = p[:auth_path]
247: else
248: # pseudo-message to find the template. The source is ignored, and the
249: # target is set according to where the template should be checked
250: # (public or private)
251: # This might still fail in the case of 'everywhere' for commands there are
252: # really only private
253: case where
254: when "?""?"
255: pseudo_target = @bot.myself
256: when :*
257: pseudo_target = m.channel
258: else
259: pseudo_target = m.server.channel(where)
260: end
261:
262: pseudo = PrivMessage.new(bot, m.server, m.source, pseudo_target, p[:stuff].to_s)
263:
264: auth_path = find_auth(pseudo)
265: end
266: debug auth_path
267:
268: if auth_path
269: allow = p[:allow]
270: if @bot.auth.permit?(botuser, auth_path, where)
271: return m.reply(_("%{user} can already do that") % {:user => botuser}) if allow
272: else
273: return m.reply(_("%{user} can't do that already") % {:user => botuser}) if !allow
274: end
275: cmd = PrivMessage.new(bot, m.server, m.source, m.target, "permissions set %{sign}%{path} %{where} for %{user}" % {
276: :path => auth_path,
277: :user => p[:user],
278: :sign => (allow ? '+' : '-'),
279: :where => p[:where].to_s
280: })
281: handle(cmd)
282: else
283: 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?") % {
284: :cmd => p[:stuff].to_s
285: })
286: end
287: end
# File lib/rbot/core/auth.rb, line 309
309: def auth_auth(m, params)
310: params[:botuser] = 'owner'
311: auth_login(m,params)
312: end
# File lib/rbot/core/auth.rb, line 329
329: def auth_autologin(m, params)
330: u = do_autologin(m.source)
331: if u.default?
332: m.reply _("I couldn't find anything to let you login automatically")
333: else
334: say_welcome(m)
335: end
336: end
# File lib/rbot/core/auth.rb, line 772
772: def auth_copy_ren_user(m, params)
773: source = Auth::BotUser.sanitize_username(params[:source])
774: dest = Auth::BotUser.sanitize_username(params[:dest])
775: return m.reply(_("please don't touch the default users")) unless
776: (["everyone", "owner"] & [source, dest]).empty?
777:
778: buser_array = @bot.auth.save_array
779: buser_hash = buser_array.inject({}) { |h, u|
780: h[u[:username]] = u
781: h
782: }
783:
784: return m.reply(_("no such botuser %{source}") % {:source=>source}) unless
785: buser_hash.keys.include?(source)
786: return m.reply(_("botuser %{dest} exists already") % {:dest=>dest}) if
787: buser_hash.keys.include?(dest)
788:
789: copying = m.message.split[1] == "copy"
790: begin
791: if copying
792: h = {}
793: buser_hash[source].each { |k, val|
794: h[k] = val.dup
795: }
796: else
797: h = buser_hash[source]
798: end
799: h[:username] = dest
800: buser_array << h if copying
801:
802: @bot.auth.load_array(buser_array, true)
803: @bot.auth.set_changed
804: call_event(:botuser, copying ? :copy : :rename, :source => source, :dest => dest)
805: rescue => e
806: return m.reply(_("failed: %{exception}") % {:exception=>e})
807: end
808: if copying
809: m.reply(_("botuser %{source} copied to %{dest}") %
810: {:source=>source, :dest=>dest})
811: else
812: m.reply(_("botuser %{source} renamed to %{dest}") %
813: {:source=>source, :dest=>dest})
814: end
815:
816: end
# File lib/rbot/core/auth.rb, line 695
695: def auth_create_user(m, params)
696: name = params[:name]
697: password = params[:password]
698: return m.reply(_("are you nuts, creating a botuser with a publicly known password?")) if m.public? and not password.nil?
699: begin
700: bu = @bot.auth.create_botuser(name, password)
701: @bot.auth.set_changed
702: rescue => e
703: m.reply(_("failed to create %{user}: %{exception}") % {:user => name, :exception => e})
704: debug e.inspect + "\n" + e.backtrace.join("\n")
705: return
706: end
707: m.reply(_("created botuser %{user}") % {:user => bu.username})
708: end
# File lib/rbot/core/auth.rb, line 293
293: def auth_deny(m, p)
294: auth_allow_deny(m, p.merge(:allow => false))
295: end
# File lib/rbot/core/auth.rb, line 723
723: def auth_destroy_user(m, params)
724: @destroy_q = [] unless defined?(@destroy_q)
725: buname = params[:name]
726: return m.reply(_("You can't destroy %{user}") % {:user => buname}) if
727: ["everyone", "owner"].include?(buname)
728: mod = params[:modifier].to_sym rescue nil
729:
730: buser_array = @bot.auth.save_array
731: buser_hash = buser_array.inject({}) { |h, u|
732: h[u[:username]] = u
733: h
734: }
735:
736: return m.reply(_("no such botuser %{user}") % {:user=>buname}) unless
737: buser_hash.keys.include?(buname)
738:
739: case mod
740: when :cancel
741: if @destroy_q.include?(buname)
742: @destroy_q.delete(buname)
743: m.reply(_("%{user} removed from the destruction queue") % {:user=>buname})
744: else
745: m.reply(_("%{user} was not queued for destruction") % {:user=>buname})
746: end
747: return
748: when nil
749: if @destroy_q.include?(buname)
750: return m.reply(_("%{user} already queued for destruction, use %{highlight}user confirm destroy %{user}%{highlight} to destroy it") % {:user=>buname, :highlight=>Bold})
751: else
752: @destroy_q << buname
753: return m.reply(_("%{user} queued for destruction, use %{highlight}user confirm destroy %{user}%{highlight} to destroy it") % {:user=>buname, :highlight=>Bold})
754: end
755: when :confirm
756: begin
757: return m.reply(_("%{user} is not queued for destruction yet") %
758: {:user=>buname}) unless @destroy_q.include?(buname)
759: buser_array.delete_if { |u|
760: u[:username] == buname
761: }
762: @destroy_q.delete(buname)
763: @bot.auth.load_array(buser_array, true)
764: @bot.auth.set_changed
765: rescue => e
766: return m.reply(_("failed: %{exception}") % {:exception => e})
767: end
768: return m.reply(_("botuser %{user} destroyed") % {:user => buname})
769: end
770: end
# File lib/rbot/core/auth.rb, line 105
105: def auth_edit_perm(m, params)
106:
107: setting = m.message.split[1] == "set"
108: splits = params[:args]
109:
110: has_for = splits[-2] == "for"
111: return usage(m) unless has_for
112:
113: begin
114: user = @bot.auth.get_botuser(splits[-1].sub(/^all$/,"everyone"))
115: rescue
116: return m.reply(_("couldn't find botuser %{name}") % {:name => splits[-1]})
117: end
118: return m.reply(_("you can't change permissions for %{username}") % {:username => user.username}) if user.owner?
119: splits.slice!(-2,2) if has_for
120:
121: cmds, locs, warns = parse_args(splits, setting)
122: errs = warns.select { |w| w.kind_of?(Exception) }
123:
124: unless errs.empty?
125: m.reply _("couldn't satisfy your request: %{errors}") % {:errors => errs.join(',')}
126: return
127: end
128:
129: if locs.empty?
130: locs << "*"
131: end
132: begin
133: locs.each { |loc|
134: ch = loc
135: if m.private?
136: ch = "?" if loc == "_"
137: else
138: ch = m.target.to_s if loc == "_"
139: end
140: cmds.each { |setval|
141: if setting
142: val = setval[0].chr == '+'
143: cmd = setval[1..-1]
144: user.set_permission(cmd, val, ch)
145: else
146: cmd = setval
147: user.reset_permission(cmd, ch)
148: end
149: }
150: }
151: rescue => e
152: m.reply "something went wrong while trying to set the permissions"
153: raise
154: end
155: @bot.auth.set_changed
156: debug "user #{user} permissions changed"
157: m.okay
158: end
# File lib/rbot/core/auth.rb, line 818
818: def auth_export(m, params)
819:
820: exportfile = @bot.path "new-auth.users"
821:
822: what = params[:things]
823:
824: has_to = what[-2] == "to"
825: if has_to
826: exportfile = @bot.path what[-1]
827: what.slice!(-2,2)
828: end
829:
830: what.delete("all")
831:
832: m.reply _("selecting data to export ...")
833:
834: buser_array = @bot.auth.save_array
835: buser_hash = buser_array.inject({}) { |h, u|
836: h[u[:username]] = u
837: h
838: }
839:
840: if what.empty?
841: we_want = buser_hash
842: else
843: we_want = buser_hash.delete_if { |key, val|
844: not what.include?(key)
845: }
846: end
847:
848: m.reply _("preparing data for export ...")
849: begin
850: yaml_hash = {}
851: we_want.each { |k, val|
852: yaml_hash[k] = {}
853: val.each { |kk, v|
854: case kk
855: when :username
856: next
857: when :netmasks
858: yaml_hash[k][kk] = []
859: v.each { |nm|
860: yaml_hash[k][kk] << {
861: :fullform => nm.fullform,
862: :casemap => nm.casemap.to_s
863: }
864: }
865: else
866: yaml_hash[k][kk] = v
867: end
868: }
869: }
870: rescue => e
871: m.reply _("failed to prepare data: %{exception}") % {:exception=>e}
872: debug e.backtrace.dup.unshift(e.inspect).join("\n")
873: return
874: end
875:
876: m.reply _("exporting to %{file} ...") % {:file=>exportfile}
877: begin
878: # m.reply yaml_hash.inspect
879: File.open(exportfile, "w") do |file|
880: file.puts YAML::dump(yaml_hash)
881: end
882: rescue => e
883: m.reply _("failed to export users: %{exception}") % {:exception=>e}
884: debug e.backtrace.dup.unshift(e.inspect).join("\n")
885: return
886: end
887: m.reply _("done")
888: end
# File lib/rbot/core/auth.rb, line 890
890: def auth_import(m, params)
891:
892: importfile = @bot.path "new-auth.users"
893:
894: what = params[:things]
895:
896: has_from = what[-2] == "from"
897: if has_from
898: importfile = @bot.path what[-1]
899: what.slice!(-2,2)
900: end
901:
902: what.delete("all")
903:
904: m.reply _("reading %{file} ...") % {:file=>importfile}
905: begin
906: yaml_hash = YAML::load_file(importfile)
907: rescue => e
908: m.reply _("failed to import from: %{exception}") % {:exception=>e}
909: debug e.backtrace.dup.unshift(e.inspect).join("\n")
910: return
911: end
912:
913: # m.reply yaml_hash.inspect
914:
915: m.reply _("selecting data to import ...")
916:
917: if what.empty?
918: we_want = yaml_hash
919: else
920: we_want = yaml_hash.delete_if { |key, val|
921: not what.include?(key)
922: }
923: end
924:
925: m.reply _("parsing data from import ...")
926:
927: buser_hash = {}
928:
929: begin
930: yaml_hash.each { |k, val|
931: buser_hash[k] = { :username => k }
932: val.each { |kk, v|
933: case kk
934: when :netmasks
935: buser_hash[k][kk] = []
936: v.each { |nm|
937: buser_hash[k][kk] << nm[:fullform].to_irc_netmask(:casemap => nm[:casemap].to_irc_casemap).to_irc_netmask(:server => @bot.server)
938: }
939: else
940: buser_hash[k][kk] = v
941: end
942: }
943: }
944: rescue => e
945: m.reply _("failed to parse data: %{exception}") % {:exception=>e}
946: debug e.backtrace.dup.unshift(e.inspect).join("\n")
947: return
948: end
949:
950: # m.reply buser_hash.inspect
951:
952: org_buser_array = @bot.auth.save_array
953: org_buser_hash = org_buser_array.inject({}) { |h, u|
954: h[u[:username]] = u
955: h
956: }
957:
958: # TODO we may want to do a(n optional) key-by-key merge
959: #
960: org_buser_hash.merge!(buser_hash)
961: new_buser_array = org_buser_hash.values
962: @bot.auth.load_array(new_buser_array, true)
963: @bot.auth.set_changed
964:
965: m.reply _("done")
966: end
# File lib/rbot/core/auth.rb, line 710
710: def auth_list_users(m, params)
711: # TODO name regexp to filter results
712: list = @bot.auth.save_array.inject([]) { |list, x| ['everyone', 'owner'].include?(x[:username]) ? list : list << x[:username] }
713: if defined?(@destroy_q)
714: list.map! { |x|
715: @destroy_q.include?(x) ? x + _(" (queued for destruction)") : x
716: }
717: end
718: return m.reply(_("I have no botusers other than the default ones")) if list.empty?
719: return m.reply(n_("botuser: %{list}", "botusers: %{list}", list.length) %
720: {:list => list.join(', ')})
721: end
# File lib/rbot/core/auth.rb, line 314
314: def auth_login(m, params)
315: begin
316: case @bot.auth.login(m.source, params[:botuser], params[:password])
317: when true
318: say_welcome(m)
319: @bot.auth.set_changed
320: else
321: m.reply _("sorry, can't do")
322: end
323: rescue => e
324: m.reply _("couldn't login: %{exception}") % {:exception => e}
325: raise
326: end
327: end
# File lib/rbot/core/auth.rb, line 461
461: def auth_manage_user(m, params)
462: splits = params[:data]
463:
464: cmd = splits.first
465: return auth_whoami(m, params) if cmd.nil?
466:
467: botuser = get_botuser_for(m.source)
468: # By default, we do stuff on the botuser the irc user is bound to
469: butarget = botuser
470:
471: has_for = splits[-2] == "for"
472: if has_for
473: butarget = @bot.auth.get_botuser(splits[-1]) rescue nil
474: return m.reply(_("no such bot user %{user}") % {:user => splits[-1]}) unless butarget
475: splits.slice!(-2,2)
476: end
477: return m.reply(_("you can't mess with %{user}") % {:user => butarget.username}) if butarget.owner? && botuser != butarget
478:
479: bools = [:autologin, "login-by-mask""login-by-mask"]
480: can_set = [:password]
481: can_addrm = [:netmasks]
482: can_reset = bools + can_set + can_addrm
483: can_show = can_reset + ["perms"]
484:
485: begin
486: case cmd.to_sym
487:
488: when :show
489: return m.reply(_("you can't see the properties of %{user}") %
490: {:user => butarget.username}) if botuser != butarget &&
491: !botuser.permit?("auth::show::other")
492:
493: case splits[1]
494: when nil, "all"
495: props = can_reset
496: when "password"
497: if botuser != butarget
498: return m.reply(_("no way I'm telling you the master password!")) if butarget == @bot.auth.botowner
499: return m.reply(_("you can't ask for someone else's password"))
500: end
501: return m.reply(_("c'mon, you can't be asking me seriously to tell you the password in public!")) if m.public?
502: return m.reply(_("the password for %{user} is %{password}") %
503: { :user => butarget.username, :password => butarget.password })
504: else
505: props = splits[1..-1]
506: end
507:
508: str = []
509:
510: props.each { |arg|
511: k = arg.to_sym
512: next if k == :password
513: case k
514: when *bools
515: if ask_bool_prop(butarget, k)
516: str << _("can %{action}") % {:action => k}
517: else
518: str << _("can not %{action}") % {:action => k}
519: end
520: when :netmasks
521: if butarget.netmasks.empty?
522: str << _("knows no netmasks")
523: else
524: str << _("knows %{netmasks}") % {:netmasks => butarget.netmasks.join(", ")}
525: end
526: end
527: }
528: return m.reply("#{butarget.username} #{str.join('; ')}")
529:
530: when :enable, :disable
531: return m.reply(_("you can't change the default user")) if butarget.default? && !botuser.permit?("auth::edit::other::default")
532: return m.reply(_("you can't edit %{user}") % {:user => butarget.username}) if butarget != botuser && !botuser.permit?("auth::edit::other")
533:
534: return m.reply(need_args(cmd)) unless splits[1]
535: things = []
536: skipped = []
537: splits[1..-1].each { |a|
538: arg = a.to_sym
539: if bools.include?(arg)
540: set_prop(butarget, arg, cmd.to_sym == :enable)
541: things << a
542: else
543: skipped << a
544: end
545: }
546:
547: m.reply(_("I ignored %{things} because %{reason}") % {
548: :things => skipped.join(', '),
549: :reason => not_args(cmd, *bools)}) unless skipped.empty?
550: if things.empty?
551: m.reply _("I haven't changed anything")
552: else
553: @bot.auth.set_changed
554: return auth_manage_user(m, {:data => ["show"] + things + ["for", butarget.username] })
555: end
556:
557: when :set
558: return m.reply(_("you can't change the default user")) if
559: butarget.default? && !botuser.permit?("auth::edit::default")
560: return m.reply(_("you can't edit %{user}") % {:user=>butarget.username}) if
561: butarget != botuser && !botuser.permit?("auth::edit::other")
562:
563: return m.reply(need_args(cmd)) unless splits[1]
564: arg = splits[1].to_sym
565: return m.reply(not_args(cmd, *can_set)) unless can_set.include?(arg)
566: argarg = splits[2]
567: return m.reply(need_args([cmd, splits[1]].join(" "))) unless argarg
568: if arg == :password && m.public?
569: return m.reply(_("is that a joke? setting the password in public?"))
570: end
571: set_prop(butarget, arg, argarg)
572: @bot.auth.set_changed
573: auth_manage_user(m, {:data => ["show", arg.to_s, "for", butarget.username] })
574:
575: when :reset
576: return m.reply(_("you can't change the default user")) if
577: butarget.default? && !botuser.permit?("auth::edit::default")
578: return m.reply(_("you can't edit %{user}") % {:user=>butarget.username}) if
579: butarget != botuser && !botuser.permit?("auth::edit::other")
580:
581: return m.reply(need_args(cmd)) unless splits[1]
582: things = []
583: skipped = []
584: splits[1..-1].each { |a|
585: arg = a.to_sym
586: if can_reset.include?(arg)
587: reset_prop(butarget, arg)
588: things << a
589: else
590: skipped << a
591: end
592: }
593:
594: m.reply(_("I ignored %{things} because %{reason}") %
595: { :things => skipped.join(', '),
596: :reason => not_args(cmd, *can_reset)}) unless skipped.empty?
597: if things.empty?
598: m.reply _("I haven't changed anything")
599: else
600: @bot.auth.set_changed
601: @bot.say(m.source, _("the password for %{user} is now %{password}") %
602: {:user => butarget.username, :password => butarget.password}) if
603: things.include?("password")
604: return auth_manage_user(m, {:data => (["show"] + things - ["password"]) + ["for", butarget.username]})
605: end
606:
607: when :add, :rm, :remove, :del, :delete
608: return m.reply(_("you can't change the default user")) if
609: butarget.default? && !botuser.permit?("auth::edit::default")
610: return m.reply(_("you can't edit %{user}") % {:user => butarget.username}) if
611: butarget != botuser && !botuser.permit?("auth::edit::other")
612:
613: arg = splits[1]
614: if arg.nil? or arg !~ /netmasks?/ or splits[2].nil?
615: return m.reply(_("I can only add/remove netmasks. See +help user add+ for more instructions"))
616: end
617:
618: method = cmd.to_sym == :add ? :add_netmask : :delete_netmask
619:
620: failed = []
621:
622: splits[2..-1].each { |mask|
623: begin
624: butarget.send(method, mask.to_irc_netmask(:server => @bot.server))
625: rescue => e
626: debug "failed with #{e.message}"
627: debug e.backtrace.join("\n")
628: failed << mask
629: end
630: }
631: m.reply "I failed to #{cmd} #{failed.join(', ')}" unless failed.empty?
632: @bot.auth.set_changed
633: return auth_manage_user(m, {:data => ["show", "netmasks", "for", butarget.username] })
634:
635: else
636: m.reply _("sorry, I don't know how to %{request}") % {:request => m.message}
637: end
638: rescue => e
639: m.reply _("couldn't %{cmd}: %{exception}") % {:cmd => cmd, :exception => e}
640: end
641: end
# File lib/rbot/core/auth.rb, line 643
643: def auth_meet(m, params)
644: nick = params[:nick]
645: if !nick
646: # we are actually responding to a 'hello' command
647: unless m.botuser.transient?
648: m.reply @bot.lang.get('hello_X') % m.botuser
649: return
650: end
651: nick = m.sourcenick
652: irc_user = m.source
653: else
654: # m.channel is always an Irc::Channel because the command is either
655: # public-only 'meet' or private/public 'hello' which was handled by
656: # the !nick case, so this shouldn't fail
657: irc_user = m.channel.users[nick]
658: return m.reply("I don't see anyone named '#{nick}' here") unless irc_user
659: end
660: # BotUser name
661: buname = params[:user] || nick
662: begin
663: call_event(:botuser,:pre_perm, {:irc_user => irc_user, :bot_user => buname})
664: met = @bot.auth.make_permanent(irc_user, buname)
665: @bot.auth.set_changed
666: call_event(:botuser,:post_perm, {:irc_user => irc_user, :bot_user => buname})
667: m.reply @bot.lang.get('hello_X') % met
668: @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 <password>' in private" % {
669: :buname => buname,
670: :pass => met.password
671: })
672: rescue RuntimeError
673: # or can this happen for other cases too?
674: # TODO autologin if forced
675: m.reply _("but I already know %{buname}" % {:buname => buname})
676: rescue => e
677: m.reply _("I had problems meeting %{nick}: %{e}" % { :nick => nick, :e => e })
678: end
679: end
# File lib/rbot/core/auth.rb, line 199
199: def auth_search_perm(m, p)
200: pattern = Regexp.new(p[:pattern].to_s)
201: results = @bot.plugins.maps.select { |k, v| k.match(pattern) }
202: count = results.length
203: max = @bot.config['send.max_lines']
204: extra = (count > max ? _(". only %{max} will be shown") : "") % { :max => max }
205: m.reply _("%{count} commands found matching %{pattern}%{extra}") % {
206: :count => count, :pattern => pattern, :extra => extra
207: }
208: return if count == 0
209: results[0,max].each { |cmd, hash|
210: m.reply _("%{cmd}: %{perms}") % {
211: :cmd => cmd,
212: :perms => hash[:auth].join(", ")
213: }
214: }
215: end
# File lib/rbot/core/auth.rb, line 681
681: def auth_tell_password(m, params)
682: user = params[:user]
683: begin
684: botuser = @bot.auth.get_botuser(params[:botuser])
685: rescue
686: return m.reply(_("couldn't find botuser %{user}") % {:user => params[:botuser]})
687: end
688: return m.reply(_("I'm not telling the master password to anyone, pal")) if botuser == @bot.auth.botowner
689: msg = _("the password for botuser %{user} is %{password}") %
690: {:user => botuser.username, :password => botuser.password}
691: @bot.say user, msg
692: @bot.say m.source, _("I told %{user} that %{message}") % {:user => user, :message => msg}
693: end
# File lib/rbot/core/auth.rb, line 160
160: def auth_view_perm(m, params)
161: begin
162: if params[:user].nil?
163: user = get_botuser_for(m.source)
164: return m.reply(_("you are owner, you can do anything")) if user.owner?
165: else
166: user = @bot.auth.get_botuser(params[:user].sub(/^all$/,"everyone"))
167: return m.reply(_("owner can do anything")) if user.owner?
168: end
169: rescue
170: return m.reply(_("couldn't find botuser %{name}") % {:name => params[:user]})
171: end
172: perm = user.perm
173: str = []
174: perm.each { |k, val|
175: next if val.perm.empty?
176: case k
177: when :*
178: str << _("on any channel: ")
179: when "?""?"
180: str << _("in private: ")
181: else
182: str << _("on #{k}: ")
183: end
184: sub = []
185: val.perm.each { |cmd, bool|
186: sub << (bool ? "+" : "-")
187: sub.last << cmd.to_s
188: }
189: str.last << sub.join(', ')
190: }
191: if str.empty?
192: m.reply _("no permissions set for %{user}") % {:user => user.username}
193: else
194: m.reply _("permissions for %{user}:: %{permissions}") %
195: { :user => user.username, :permissions => str.join('; ')}
196: end
197: end
# File lib/rbot/core/auth.rb, line 342
342: def auth_whoami(m, params)
343: m.reply _("you are %{who}") % {
344: :who => get_botusername_for(m.source).gsub(
345: /^everyone$/, _("no one that I know")).gsub(
346: /^owner$/, _("my boss"))
347: }
348: end
# File lib/rbot/core/auth.rb, line 350
350: def auth_whois(m, params)
351: return auth_whoami(m, params) if !m.public?
352: u = m.channel.users[params[:user]]
353:
354: return m.reply("I don't see anyone named '#{params[:user]}' here") unless u
355:
356: m.reply _("#{params[:user]} is %{who}") % {
357: :who => get_botusername_for(u).gsub(
358: /^everyone$/, _("no one that I know")).gsub(
359: /^owner$/, _("my boss"))
360: }
361: end
# File lib/rbot/core/auth.rb, line 338
338: def do_autologin(user)
339: @bot.auth.autologin(user)
340: end
# File lib/rbot/core/auth.rb, line 217
217: def find_auth(pseudo)
218: k = pseudo.plugin.intern
219: cmds = @bot.plugins.commands
220: auth = nil
221: if cmds.has_key?(k)
222: cmds[k][:botmodule].handler.each do |tmpl|
223: options, failure = tmpl.recognize(pseudo)
224: next if options.nil?
225: auth = tmpl.options[:full_auth_path]
226: break
227: end
228: end
229: return auth
230: end
# File lib/rbot/core/auth.rb, line 297
297: def get_botuser_for(user)
298: @bot.auth.irc_to_botuser(user)
299: end
# File lib/rbot/core/auth.rb, line 301
301: def get_botusername_for(user)
302: get_botuser_for(user).username
303: end
# File lib/rbot/core/auth.rb, line 363
363: def help(cmd, topic="")
364: case cmd
365: when "login"
366: return _("login [<botuser>] [<pass>]: logs in to the bot as botuser <botuser> with password <pass>. When using the full form, you must contact the bot in private. <pass> can be omitted if <botuser> allows login-by-mask and your netmask is among the known ones. if <botuser> is omitted too autologin will be attempted")
367: when "whoami"
368: return _("whoami: names the botuser you're linked to")
369: when "who"
370: return _("who is <user>: names the botuser <user> is linked to")
371: when /^permission/
372: case topic
373: when "syntax"
374: 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")
375: when "set", "reset", "[re]set", "(re)set"
376: return _("permissions [re]set <permission> [in <channel>] for <user>: sets or resets the permissions for botuser <user> in channel <channel> (use ? to change the permissions for private addressing)")
377: when "view"
378: return _("permissions view [for <user>]: display the permissions for user <user>")
379: when "search"
380: return _("permissions search <pattern>: display the permissions associated with the commands matching <pattern>")
381: else
382: return _("permission topics: syntax, (re)set, view, search")
383: end
384: when "user"
385: case topic
386: when "show"
387: return _("user show <what> : shows info about the user; <what> can be any of autologin, login-by-mask, netmasks")
388: when /^(en|dis)able/
389: return _("user enable|disable <what> : turns on or off <what> (autologin, login-by-mask)")
390: when "set"
391: return _("user set password <blah> : sets the user password to <blah>; passwords can only contain upper and lowercase letters and numbers, and must be at least 4 characters long")
392: when "add", "rm"
393: return _("user add|rm netmask <mask> : adds/removes netmask <mask> from the list of netmasks known to the botuser you're linked to")
394: when "reset"
395: return _("user reset <what> : resets <what> to the default values. <what> 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)")
396: when "tell"
397: return _("user tell <who> the password for <botuser> : contacts <who> in private to tell him/her the password for <botuser>")
398: when "create"
399: return _("user create <name> <password> : create botuser named <name> with password <password>. The password can be omitted, in which case a random one will be generated. The <name> should only contain alphanumeric characters and the underscore (_)")
400: when "list"
401: return _("user list : lists all the botusers")
402: when "destroy"
403: return _("user destroy <botuser> : destroys <botuser>. This function %{highlight}must%{highlight} be called in two steps. On the first call <botuser> is queued for destruction. On the second call, which must be in the form 'user confirm destroy <botuser>', the botuser will be destroyed. If you want to cancel the destruction, issue the command 'user cancel destroy <botuser>'") % {:highlight => Bold}
404: else
405: return _("user topics: show, enable|disable, add|rm netmask, set, reset, tell, create, list, destroy")
406: end
407: when "auth"
408: return _("auth <masterpassword>: log in as the bot owner; other commands: login, whoami, permissions syntax, permissions [re]set, permissions view, user, meet, hello, allow, deny")
409: when "meet"
410: return _("meet <nick> [as <user>]: creates a bot user for nick, calling it user (defaults to the nick itself)")
411: when "hello"
412: return _("hello: creates a bot user for the person issuing the command")
413: when "allow"
414: return [
415: _("allow <user> to do <sample command> [<where>]: gives botuser <user> the permissions to execute a command such as the provided sample command"),
416: _("(in private or in channel, according to the optional <where>)."),
417: _("<sample command> should be a full command, not just the command keyword --"),
418: _("correct: allow user to do addquote stuff --"),
419: _("wrong: allow user to do addquote.")
420: ].join(" ")
421: when "deny"
422: return [
423: _("deny <user> from doing <sample command> [<where>]: removes from botuser <user> the permissions to execute a command such as the provided sample command"),
424: _("(in private or in channel, according to the optional <where>)."),
425: _("<sample command> should be a full command, not just the command keyword --"),
426: _("correct: deny user from doing addquote stuff --"),
427: _("wrong: deny user from doing addquote.")
428: ].join(" ")
429: else
430: return _("auth commands: auth, login, whoami, who, permission[s], user, meet, hello, allow, deny")
431: end
432: end
# File lib/rbot/core/auth.rb, line 37
37: def load_array(key=:default, forced=false)
38: debug "loading botusers (#{key}): #{@registry[key].pretty_inspect}"
39: @bot.auth.load_array(@registry[key], forced) if @registry.has_key?(key)
40: if @bot.auth.botowner.password != @bot.config['auth.password']
41: error "Master password is out of sync!"
42: debug " db password: #{@bot.auth.botowner.password}"
43: debug "conf password: #{@bot.config['auth.password']}"
44: error "Using conf password"
45: @bot.auth.botowner.password = @bot.config['auth.password']
46: end
47: end
# File lib/rbot/core/auth.rb, line 434
434: def need_args(cmd)
435: _("sorry, I need more arguments to %{command}") % {:command => cmd}
436: end
# File lib/rbot/core/auth.rb, line 438
438: def not_args(cmd, *stuff)
439: _("I can only %{command} these: %{arguments}") %
440: {:command => cmd, :arguments => stuff.join(', ')}
441: end
The permission parameters accept arguments with the following syntax:
cmd_path... [on #chan .... | in here | in private]
This auxiliary method scans the array ar to see if it matches the given syntax: it expects + or - signs in front of cmd_path elements when setting = true
It returns an array whose first element is the array of cmd_path, the second element is an array of locations and third an array of warnings occurred while parsing the strings
# File lib/rbot/core/auth.rb, line 59
59: def parse_args(ar, setting)
60: cmds = []
61: locs = []
62: warns = []
63: doing_cmds = true
64: next_must_be_chan = false
65: want_more = false
66: last_idx = 0
67: ar.each_with_index { |x, i|
68: if doing_cmds # parse cmd_path
69: # check if the list is done
70: if x == "on" or x == "in"
71: doing_cmds = false
72: next_must_be_chan = true if x == "on"
73: next
74: end
75: if "+-".include?(x[0])
76: warns << ArgumentError.new(_("please do not use + or - in front of command %{command} when resetting") % {:command => x}) unless setting
77: else
78: warns << ArgumentError.new(_("+ or - expected in front of %{string}") % {:string => x}) if setting
79: end
80: cmds << x
81: else # parse locations
82: if x[-1].chr == ','
83: want_more = true
84: else
85: want_more = false
86: end
87: case next_must_be_chan
88: when false
89: locs << x.gsub(/^here$/,'_').gsub(/^private$/,'?')
90: else
91: warns << ArgumentError.new(_("'%{string}' doesn't look like a channel name") % {:string => x}) unless @bot.server.supports[:chantypes].include?(x[0])
92: locs << x
93: end
94: unless want_more
95: last_idx = i
96: break
97: end
98: end
99: }
100: warns << _("trailing comma") if want_more
101: warns << _("you probably forgot a comma") unless last_idx == ar.length - 1
102: return cmds, locs, warns
103: end
# File lib/rbot/core/auth.rb, line 451
451: def reset_prop(botuser, prop)
452: k = prop.to_s.gsub("-","_")
453: botuser.send( ("reset_"+k).to_sym)
454: end
# File lib/rbot/core/auth.rb, line 29
29: def save_array(key=:default)
30: if @bot.auth.changed?
31: @registry[key] = @bot.auth.save_array
32: @bot.auth.reset_changed
33: debug "saved botusers (#{key}): #{@registry[key].pretty_inspect}"
34: end
35: end
# File lib/rbot/core/auth.rb, line 305
305: def say_welcome(m)
306: m.reply _("welcome, %{user}") % {:user => get_botusername_for(m.source)}
307: end
# File lib/rbot/core/auth.rb, line 443
443: def set_prop(botuser, prop, val)
444: k = prop.to_s.gsub("-","_")
445: botuser.send( (k + "=").to_sym, val)
446: if prop == :password and botuser == @bot.auth.botowner
447: @bot.config.items['auth.password''auth.password'].set_string(@bot.auth.botowner.password)
448: end
449: end