Class AuthModule
In: lib/rbot/core/auth.rb
Parent: CoreBotModule
AuthModule CoreBotModule dot/f_20.png
Author:Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>

Methods

Public Class methods

[Source]

    # 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

Public Instance methods

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/rbot/core/auth.rb, line 338
338:   def do_autologin(user)
339:     @bot.auth.autologin(user)
340:   end

[Source]

     # 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

[Source]

     # File lib/rbot/core/auth.rb, line 297
297:   def get_botuser_for(user)
298:     @bot.auth.irc_to_botuser(user)
299:   end

[Source]

     # File lib/rbot/core/auth.rb, line 301
301:   def get_botusername_for(user)
302:     get_botuser_for(user).username
303:   end

[Source]

     # 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

[Source]

    # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

    # File lib/rbot/core/auth.rb, line 25
25:   def save
26:     save_array
27:   end

[Source]

    # 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

[Source]

     # 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

[Source]

     # 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

[Validate]