[Rt-commit] r5413 - in RT-Extension-ResetPassword: . html html/Callbacks/RT-Extension-ResetPassword html/Callbacks/RT-Extension-ResetPassword/Elements html/Callbacks/RT-Extension-ResetPassword/Elements/Login html/NoAuth html/NoAuth/ResetPassword html/NoAuth/ResetPassword/Reset inc inc/.author inc/Module lib lib/RT lib/RT/Extension

jesse at bestpractical.com jesse at bestpractical.com
Tue Jun 20 16:26:34 EDT 2006


Author: jesse
Date: Tue Jun 20 16:26:32 2006
New Revision: 5413

Added:
   RT-Extension-ResetPassword/MANIFEST
   RT-Extension-ResetPassword/META.yml
   RT-Extension-ResetPassword/Makefile.PL
   RT-Extension-ResetPassword/README
   RT-Extension-ResetPassword/html/
   RT-Extension-ResetPassword/html/Callbacks/
   RT-Extension-ResetPassword/html/Callbacks/RT-Extension-ResetPassword/
   RT-Extension-ResetPassword/html/Callbacks/RT-Extension-ResetPassword/Elements/
   RT-Extension-ResetPassword/html/Callbacks/RT-Extension-ResetPassword/Elements/Login/
   RT-Extension-ResetPassword/html/Callbacks/RT-Extension-ResetPassword/Elements/Login/Default
   RT-Extension-ResetPassword/html/NoAuth/
   RT-Extension-ResetPassword/html/NoAuth/ResetPassword/
   RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Request.html
   RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Reset/
   RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Reset/dhandler
   RT-Extension-ResetPassword/inc/
   RT-Extension-ResetPassword/inc/.author/
   RT-Extension-ResetPassword/inc/Module/
   RT-Extension-ResetPassword/inc/Module/Install.pm
   RT-Extension-ResetPassword/lib/
   RT-Extension-ResetPassword/lib/RT/
   RT-Extension-ResetPassword/lib/RT/Extension/
   RT-Extension-ResetPassword/lib/RT/Extension/ResetPassword.pm

Log:
* Initail import

Added: RT-Extension-ResetPassword/MANIFEST
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/MANIFEST	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,18 @@
+html/Callbacks/RT-Extension-ResetPassword/Elements/Login/Default
+html/NoAuth/ResetPassword/Request.html
+html/NoAuth/ResetPassword/Reset/dhandler
+inc/Module/Install.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install/RTx.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+lib/RT/Extension/ResetPassword.pm
+Makefile.PL
+MANIFEST			This list of files
+META.yml
+README
+todo

Added: RT-Extension-ResetPassword/META.yml
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/META.yml	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,11 @@
+abstract: RT Extension-ResetPassword Extension
+distribution_type: module
+generated_by: Module::Install version 0.61
+license: unknown
+name: RT-Extension-ResetPassword
+no_index: 
+  directory: 
+    - html
+    - inc
+    - t
+version: 0.01

Added: RT-Extension-ResetPassword/Makefile.PL
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/Makefile.PL	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,3 @@
+use inc::Module::Install;
+RTx('RT-Extension-ResetPassword');
+&WriteAll;

Added: RT-Extension-ResetPassword/README
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/README	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,21 @@
+This extension for RT adds a new "Forgot your password?" link to the front
+of your RT instance. Any user can request that RT send them a password
+reset token by email.  RT will send the user a one-time URL which he or
+she can use to reset her password. This extension allows _all_ users to
+reset their passwords by email. There isn't yet an option to only allow
+staff users or non-staff users to reset their passwords.
+
+This extension should be compatible with RT 3.4 and RT 3.6.
+
+To install this extension:
+
+perl Makefile.PL
+make install
+
+Copyright 2006 Best Practical Solutions, LLC. 
+
+This software is distributed under the same license as Perl 5.8.8.
+
+For commercial support, please contact sales at bestpractical.com
+
+

Added: RT-Extension-ResetPassword/html/Callbacks/RT-Extension-ResetPassword/Elements/Login/Default
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/html/Callbacks/RT-Extension-ResetPassword/Elements/Login/Default	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,2 @@
+<br/><div id="lostpassword" style="align:left;clear:both;">
+<a href="/NoAuth/ResetPassword/Request.html"><&|/l&>Forgot your password?</&></a></div>

Added: RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Request.html
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Request.html	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,95 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%# 
+%# COPYRIGHT:
+%#  
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
+%#                                          <jesse at bestpractical.com>
+%# 
+%# (Except where explicitly superseded by other copyright notices)
+%# 
+%# 
+%# LICENSE:
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%# 
+%# 
+%# CONTRIBUTION SUBMISSION POLICY:
+%# 
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%# 
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%# 
+%# END BPS TAGGED BLOCK }}}
+<& /Elements/Header, Title => $title &>
+<div id="body" class="login-body">
+
+<h1><%$title%></h1>
+<& /Elements/ListActions, actions => \@actions  &>
+<p>
+<&|/l&>RT can send you an email message with a link that will allow you to reset your password.</&>
+<form method="post" action="Request.html">
+    <&|/l&>Email address</&>:<input name="Email" value="" />
+    <input type="submit" class="button" value="<%loc('Send it!')%>" />
+</form>
+</div>
+
+<%INIT>
+my @actions;
+
+my $title = loc("Reset your password");
+
+if ($ARGS{'Email'} ) {
+    my $u = RT::User->new($RT::SystemUser);
+    $u->LoadByCols(EmailAddress => $ARGS{'Email'});
+    if ($u->id) {
+    my $token = Digest::MD5->new()->add( $u->id, $u->__Value('Password'),
+        $RT::DatabasePassword, $u->LastUpdated, '/NoAuth/ResetPassword/Reset')->hexdigest();
+
+    my $msg = <<EOF;
+Greetings,
+
+Someone at @{[$ENV{'REMOTE_ADDR'}]} requested that RT send you this message
+allowing you to reset your password. If you didn't request this message, please
+notify your RT administrator immediately.
+
+To reset your password, click on the following URL and enter your new password:
+
+@{[$RT::WebURL]}/NoAuth/ResetPassword/Reset/@{[$token]}/@{[$u->id]}
+
+
+EOF
+
+RT::Interface::Email::MailError( To => $u->EmailAddress, From => $RT::OwnerEmail, Subject => 'RT Password Reset Request', Explanation => $msg, LogLevel=> 'info');
+
+
+push @actions, loc("RT has sent you an email message with instructions about how to reset your password");
+} else {
+push @actions, loc("RT couldn't find a user with that email address. Give it another try?");
+
+}
+}
+
+</%INIT>

Added: RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Reset/dhandler
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/html/NoAuth/ResetPassword/Reset/dhandler	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,78 @@
+<%init>
+# The URL They're visitng
+# @{[$RT::WebURL]}/NoAuth/Reset/@{[$token]}/@{[$u->id]}
+my @results;
+my $show_form    = 1;
+my $title        = loc('Reset your password');
+my $virtual_path = $m->dhandler_arg();
+my ( $submitted_token, $id ) = split( '/', $virtual_path );
+my $token;
+# Validate the token
+my $u = RT::User->new($RT::SystemUser);
+$u->LoadByCols( id => $id );
+if ( $u->id ) {
+    $token = Digest::MD5->new()->add( $u->id, $u->__Value('Password'),
+        $RT::DatabasePassword, $u->LastUpdated,
+        '/NoAuth/ResetPassword/Reset' )->hexdigest();
+}
+else {
+    push @results,
+        loc("Something went wrong. Please contact your RT administrator.");
+    $show_form = 0;
+}
+
+# If the token validation fails, throw them an error
+if ( $submitted_token ne $token ) {
+    push @results,
+        loc(
+        "It looks like the URL you clicked on has expired or wasn't quite right. Maybe you didn't paste the whole thing?"
+        );
+    $show_form = 0;
+}
+
+# if the validation succeeds, continue on
+else {
+
+    # If they've supplied a new password twice, change it and redirect to home
+    if (    ( $submitted_token eq $token )
+        and $ARGS{'password'}
+        and $ARGS{'password2'}
+        and ( $ARGS{'password'} eq $ARGS{'password2'} ) )
+    {
+        my ( $val, $msg ) = $u->SetPassword( $ARGS{'password'} );
+        push @results, $msg;
+        if ($val) { $show_form = 0;}
+    }
+    elsif ( $ARGS{'password'} ) {
+        push @results, loc("The two passwords you typed didn't match.");
+    }
+
+}
+# otherwise, show the form
+
+
+</%init>
+<& /Elements/Header, Title => $title &>
+<div id="body" class="login-body">
+
+<h1><%$title%></h1>
+<& /Elements/ListActions, actions => \@results  &>
+<p>
+
+
+% if ($show_form) {
+<form method="post" action="<%$id%>">
+<table>
+  <tr>
+    <td class="label"><label name="password"><&|/l&>New password</&>:</label></td>
+    <td class="value"><input name="password" type="password"></td>
+  </tr>
+  <tr>
+    <td class="label"><label name="password2"><&|/l&>Once more</&>:</label></td>
+    <td class="value"><input name="password2" type="password"></td>
+  </tr>
+</table>
+<input type ="submit" value ="<%loc('Change password')%>">
+</form>
+%}
+<a href="<%$RT::WebURL|n%>"><&|/l&>Login</&></a>

Added: RT-Extension-ResetPassword/inc/Module/Install.pm
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/inc/Module/Install.pm	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,281 @@
+#line 1
+package Module::Install;
+
+# For any maintainers:
+# The load order for Module::Install is a bit magic.
+# It goes something like this...
+#
+# IF ( host has Module::Install installed, creating author mode ) {
+#     1. Makefile.PL calls "use inc::Module::Install"
+#     2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
+#     3. The installed version of inc::Module::Install loads
+#     4. inc::Module::Install calls "require Module::Install"
+#     5. The ./inc/ version of Module::Install loads
+# } ELSE {
+#     1. Makefile.PL calls "use inc::Module::Install"
+#     2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
+#     3. The ./inc/ version of Module::Install loads
+# }
+
+use 5.004;
+use strict 'vars';
+
+use vars qw{$VERSION};
+BEGIN {
+    # All Module::Install core packages now require synchronised versions.
+    # This will be used to ensure we don't accidentally load old or
+    # different versions of modules.
+    # This is not enforced yet, but will be some time in the next few
+    # releases once we can make sure it won't clash with custom
+    # Module::Install extensions.
+    $VERSION = '0.63';
+}
+
+# Whether or not inc::Module::Install is actually loaded, the
+# $INC{inc/Module/Install.pm} is what will still get set as long as
+# the caller loaded module this in the documented manner.
+# If not set, the caller may NOT have loaded the bundled version, and thus
+# they may not have a MI version that works with the Makefile.PL. This would
+# result in false errors or unexpected behaviour. And we don't want that.
+my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
+unless ( $INC{$file} ) {
+    die <<"END_DIE";
+Please invoke ${\__PACKAGE__} with:
+
+    use inc::${\__PACKAGE__};
+
+not:
+
+    use ${\__PACKAGE__};
+
+END_DIE
+}
+
+# If the script that is loading Module::Install is from the future,
+# then make will detect this and cause it to re-run over and over
+# again. This is bad. Rather than taking action to touch it (which
+# is unreliable on some platforms and requires write permissions)
+# for now we should catch this and refuse to run.
+if ( -f $0 and (stat($0))[9] > time ) {
+	die << "END_DIE";
+Your installer $0 has a modification time in the future.
+
+This is known to create infinite loops in make.
+
+Please correct this, then run $0 again.
+
+END_DIE
+}
+
+use Cwd        ();
+use File::Find ();
+use File::Path ();
+use FindBin;
+
+*inc::Module::Install::VERSION = *VERSION;
+ at inc::Module::Install::ISA     = __PACKAGE__;
+
+sub autoload {
+    my $self = shift;
+    my $who  = $self->_caller;
+    my $cwd  = Cwd::cwd();
+    my $sym  = "${who}::AUTOLOAD";
+    $sym->{$cwd} = sub {
+        my $pwd = Cwd::cwd();
+        if ( my $code = $sym->{$pwd} ) {
+            # delegate back to parent dirs
+            goto &$code unless $cwd eq $pwd;
+        }
+        $$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
+        unshift @_, ($self, $1);
+        goto &{$self->can('call')} unless uc($1) eq $1;
+    };
+}
+
+sub import {
+    my $class = shift;
+    my $self  = $class->new(@_);
+    my $who   = $self->_caller;
+
+    unless ( -f $self->{file} ) {
+        require "$self->{path}/$self->{dispatch}.pm";
+        File::Path::mkpath("$self->{prefix}/$self->{author}");
+        $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
+        $self->{admin}->init;
+        @_ = ($class, _self => $self);
+        goto &{"$self->{name}::import"};
+    }
+
+    *{"${who}::AUTOLOAD"} = $self->autoload;
+    $self->preload;
+
+    # Unregister loader and worker packages so subdirs can use them again
+    delete $INC{"$self->{file}"};
+    delete $INC{"$self->{path}.pm"};
+}
+
+sub preload {
+    my ($self) = @_;
+
+    unless ( $self->{extensions} ) {
+        $self->load_extensions(
+            "$self->{prefix}/$self->{path}", $self
+        );
+    }
+
+    my @exts = @{$self->{extensions}};
+    unless ( @exts ) {
+        my $admin = $self->{admin};
+        @exts = $admin->load_all_extensions;
+    }
+
+    my %seen;
+    foreach my $obj ( @exts ) {
+        while (my ($method, $glob) = each %{ref($obj) . '::'}) {
+            next unless $obj->can($method);
+            next if $method =~ /^_/;
+            next if $method eq uc($method);
+            $seen{$method}++;
+        }
+    }
+
+    my $who = $self->_caller;
+    foreach my $name ( sort keys %seen ) {
+        *{"${who}::$name"} = sub {
+            ${"${who}::AUTOLOAD"} = "${who}::$name";
+            goto &{"${who}::AUTOLOAD"};
+        };
+    }
+}
+
+sub new {
+    my ($class, %args) = @_;
+
+    # ignore the prefix on extension modules built from top level.
+    my $base_path = Cwd::abs_path($FindBin::Bin);
+    unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
+        delete $args{prefix};
+    }
+
+    return $args{_self} if $args{_self};
+
+    $args{dispatch} ||= 'Admin';
+    $args{prefix}   ||= 'inc';
+    $args{author}   ||= ($^O eq 'VMS' ? '_author' : '.author');
+    $args{bundle}   ||= 'inc/BUNDLES';
+    $args{base}     ||= $base_path;
+    $class =~ s/^\Q$args{prefix}\E:://;
+    $args{name}     ||= $class;
+    $args{version}  ||= $class->VERSION;
+    unless ( $args{path} ) {
+        $args{path}  = $args{name};
+        $args{path}  =~ s!::!/!g;
+    }
+    $args{file}     ||= "$args{base}/$args{prefix}/$args{path}.pm";
+
+    bless( \%args, $class );
+}
+
+sub call {
+	my ($self, $method) = @_;
+	my $obj = $self->load($method) or return;
+        splice(@_, 0, 2, $obj);
+	goto &{$obj->can($method)};
+}
+
+sub load {
+    my ($self, $method) = @_;
+
+    $self->load_extensions(
+        "$self->{prefix}/$self->{path}", $self
+    ) unless $self->{extensions};
+
+    foreach my $obj (@{$self->{extensions}}) {
+        return $obj if $obj->can($method);
+    }
+
+    my $admin = $self->{admin} or die <<"END_DIE";
+The '$method' method does not exist in the '$self->{prefix}' path!
+Please remove the '$self->{prefix}' directory and run $0 again to load it.
+END_DIE
+
+    my $obj = $admin->load($method, 1);
+    push @{$self->{extensions}}, $obj;
+
+    $obj;
+}
+
+sub load_extensions {
+    my ($self, $path, $top) = @_;
+
+    unless ( grep { lc $_ eq lc $self->{prefix} } @INC ) {
+        unshift @INC, $self->{prefix};
+    }
+
+    foreach my $rv ( $self->find_extensions($path) ) {
+        my ($file, $pkg) = @{$rv};
+        next if $self->{pathnames}{$pkg};
+
+        local $@;
+        my $new = eval { require $file; $pkg->can('new') };
+        unless ( $new ) {
+            warn $@ if $@;
+            next;
+        }
+        $self->{pathnames}{$pkg} = delete $INC{$file};
+        push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
+    }
+
+    $self->{extensions} ||= [];
+}
+
+sub find_extensions {
+    my ($self, $path) = @_;
+
+    my @found;
+    File::Find::find( sub {
+        my $file = $File::Find::name;
+        return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
+        my $subpath = $1;
+        return if lc($subpath) eq lc($self->{dispatch});
+
+        $file = "$self->{path}/$subpath.pm";
+        my $pkg = "$self->{name}::$subpath";
+        $pkg =~ s!/!::!g;
+
+        # If we have a mixed-case package name, assume case has been preserved
+        # correctly.  Otherwise, root through the file to locate the case-preserved
+        # version of the package name.
+        if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
+            open PKGFILE, "<$subpath.pm" or die "find_extensions: Can't open $subpath.pm: $!";
+            my $in_pod = 0;
+            while ( <PKGFILE> ) {
+                $in_pod = 1 if /^=\w/;
+                $in_pod = 0 if /^=cut/;
+                next if ($in_pod || /^=cut/);  # skip pod text
+                next if /^\s*#/;               # and comments
+                if ( m/^\s*package\s+($pkg)\s*;/i ) {
+                    $pkg = $1;
+                    last;
+                }
+            }
+            close PKGFILE;
+        }
+
+        push @found, [ $file, $pkg ];
+    }, $path ) if -d $path;
+
+    @found;
+}
+
+sub _caller {
+    my $depth = 0;
+    my $call  = caller($depth);
+    while ( $call eq __PACKAGE__ ) {
+        $depth++;
+        $call = caller($depth);
+    }
+    return $call;
+}
+
+1;

Added: RT-Extension-ResetPassword/lib/RT/Extension/ResetPassword.pm
==============================================================================
--- (empty file)
+++ RT-Extension-ResetPassword/lib/RT/Extension/ResetPassword.pm	Tue Jun 20 16:26:32 2006
@@ -0,0 +1,5 @@
+package RT::Extension::ResetPassword;
+
+our $VERSION = '0.02';
+
+1;


More information about the Rt-commit mailing list