-# BEGIN LICENSE BLOCK
+# {{{ BEGIN BPS TAGGED BLOCK
#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC
+# <jesse@bestpractical.com>
#
-# (Except where explictly superceded by other copyright notices)
+# (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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
-# Unless otherwise specified, all modifications, corrections or
-# extensions to this work which alter its source code become the
-# property of Best Practical Solutions, LLC when submitted for
-# inclusion in the work.
+# 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 LICENSE BLOCK
+# }}} END BPS TAGGED BLOCK
=head1 NAME
RT::User - RT User object
use Digest::MD5;
use RT::Principals;
use RT::ACE;
+use RT::EmailParser;
# {{{ sub _Accessible
-sub _ClassAccessible {
+sub _OverlayAccessible {
{
-
- id =>
- {read => 1, type => 'int(11)', default => ''},
- Name =>
- {read => 1, write => 1, public => 1, admin => 1, type => 'varchar(120)', default => ''},
- Password =>
- { write => 1, type => 'varchar(40)', default => ''},
- Comments =>
- {read => 1, write => 1, admin => 1, type => 'blob', default => ''},
- Signature =>
- {read => 1, write => 1, type => 'blob', default => ''},
- EmailAddress =>
- {read => 1, write => 1, public => 1, type => 'varchar(120)', default => ''},
- FreeformContactInfo =>
- {read => 1, write => 1, type => 'blob', default => ''},
- Organization =>
- {read => 1, write => 1, public => 1, admin => 1, type => 'varchar(200)', default => ''},
- RealName =>
- {read => 1, write => 1, public => 1, type => 'varchar(120)', default => ''},
- NickName =>
- {read => 1, write => 1, public => 1, type => 'varchar(16)', default => ''},
- Lang =>
- {read => 1, write => 1, public => 1, type => 'varchar(16)', default => ''},
- EmailEncoding =>
- {read => 1, write => 1, public => 1, type => 'varchar(16)', default => ''},
- WebEncoding =>
- {read => 1, write => 1, public => 1, type => 'varchar(16)', default => ''},
- ExternalContactInfoId =>
- {read => 1, write => 1, public => 1, admin => 1, type => 'varchar(100)', default => ''},
- ContactInfoSystem =>
- {read => 1, write => 1, public => 1, admin => 1, type => 'varchar(30)', default => ''},
- ExternalAuthId =>
- {read => 1, write => 1, public => 1, admin => 1, type => 'varchar(100)', default => ''},
- AuthSystem =>
- {read => 1, write => 1, public => 1, admin => 1,type => 'varchar(30)', default => ''},
- Gecos =>
- {read => 1, write => 1, public => 1, admin => 1, type => 'varchar(16)', default => ''},
-
- PGPKey => {
- {read => 1, write => 1, public => 1, admin => 1, type => 'text', default => ''},
- },
- HomePhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
- WorkPhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
- MobilePhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
- PagerPhone =>
- {read => 1, write => 1, type => 'varchar(30)', default => ''},
- Address1 =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
- Address2 =>
- {read => 1, write => 1, type => 'varchar(200)', default => ''},
- City =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
- State =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
- Zip =>
- {read => 1, write => 1, type => 'varchar(16)', default => ''},
- Country =>
- {read => 1, write => 1, type => 'varchar(50)', default => ''},
- Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => ''},
- Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
- LastUpdatedBy =>
- {read => 1, auto => 1, type => 'int(11)', default => ''},
- LastUpdated =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
-
- }
-};
+
+ Name => { public => 1, admin => 1 },
+ Password => { read => 0 },
+ EmailAddress => { public => 1 },
+ Organization => { public => 1, admin => 1 },
+ RealName => { public => 1 },
+ NickName => { public => 1 },
+ Lang => { public => 1 },
+ EmailEncoding => { public => 1 },
+ WebEncoding => { public => 1 },
+ ExternalContactInfoId => { public => 1, admin => 1 },
+ ContactInfoSystem => { public => 1, admin => 1 },
+ ExternalAuthId => { public => 1, admin => 1 },
+ AuthSystem => { public => 1, admin => 1 },
+ Gecos => { public => 1, admin => 1 },
+ PGPKey => { public => 1, admin => 1 },
+
+ }
+}
+
# }}}
@_ # get the real argumentlist
);
-
- $args{'EmailAddress'} = $self->CanonicalizeEmailAddress($args{'EmailAddress'});
-
#Check the ACL
unless ( $self->CurrentUser->HasRight(Right => 'AdminUsers', Object => $RT::System) ) {
return ( 0, $self->loc('No permission to create users') );
}
+ unless ($self->CanonicalizeUserInfo(\%args)) {
+ return ( 0, $self->loc("Could not set user info") );
+ }
+
+ $args{'EmailAddress'} = $self->CanonicalizeEmailAddress($args{'EmailAddress'});
+
+ # if the user doesn't have a name defined, set it to the email address
+ $args{'Name'} = $args{'EmailAddress'} unless ($args{'Name'});
+
+
+
# Privileged is no longer a column in users
my $privileged = $args{'Privileged'};
delete $args{'Privileged'};
#TODO Specify some sensible defaults.
- unless ( defined( $args{'Name'} ) ) {
+ unless ( $args{'Name'} ) {
+ use Data::Dumper;
+ $RT::Logger->crit(Dumper \%args);
return ( 0, $self->loc("Must specify 'Name' attribute") );
}
my $principal_id = $principal->Create(PrincipalType => 'User',
Disabled => $args{'Disabled'},
ObjectId => '0');
- $principal->__Set(Field => 'ObjectId', Value => $principal_id);
# If we couldn't create a principal Id, get the fuck out.
unless ($principal_id) {
$RT::Handle->Rollback();
- $RT::Logger->crit("Couldn't create a Principal on new user create. Strange things are afoot at the circle K");
+ $RT::Logger->crit("Couldn't create a Principal on new user create.");
+ $RT::Logger->crit("Strange things are afoot at the circle K");
return ( 0, $self->loc('Could not create user') );
}
+ $principal->__Set(Field => 'ObjectId', Value => $principal_id);
delete $args{'Disabled'};
$self->SUPER::Create(id => $principal_id , %args);
#If the create failed.
unless ($id) {
+ $RT::Handle->Rollback();
$RT::Logger->error("Could not create a new user - " .join('-'. %args));
return ( 0, $self->loc('Could not create user') );
}
-
- #TODO post 2.0
- #if ($args{'SendWelcomeMessage'}) {
- # #TODO: Check if the email exists and looks valid
- # #TODO: Send the user a "welcome message"
- #}
-
-
-
my $aclstash = RT::Group->new($self->CurrentUser);
my $stash_id = $aclstash->_CreateACLEquivalenceGroup($principal);
unless ($stash_id) {
$RT::Handle->Rollback();
- $RT::Logger->crit("Couldn't stash the user in groumembers");
+ $RT::Logger->crit("Couldn't stash the user in groupmembers");
return ( 0, $self->loc('Could not create user') );
}
- $RT::Handle->Commit;
- #$RT::Logger->debug("Adding the user as a member of everyone");
my $everyone = RT::Group->new($self->CurrentUser);
$everyone->LoadSystemInternalGroup('Everyone');
- $everyone->AddMember($self->PrincipalId);
+ unless ($everyone->id) {
+ $RT::Logger->crit("Could not load Everyone group on user creation.");
+ $RT::Handle->Rollback();
+ return ( 0, $self->loc('Could not create user') );
+ }
+
+
+ my ($everyone_id, $everyone_msg) = $everyone->_AddMember( InsideTransaction => 1, PrincipalId => $self->PrincipalId);
+ unless ($everyone_id) {
+ $RT::Logger->crit("Could not add user to Everyone group on user creation.");
+ $RT::Logger->crit($everyone_msg);
+ $RT::Handle->Rollback();
+ return ( 0, $self->loc('Could not create user') );
+ }
+
+ my $access_class = RT::Group->new($self->CurrentUser);
if ($privileged) {
- my $priv = RT::Group->new($self->CurrentUser);
- #$RT::Logger->debug("Making ".$self->Id." a privileged user");
- $priv->LoadSystemInternalGroup('Privileged');
- $priv->AddMember($self->PrincipalId);
+ $access_class->LoadSystemInternalGroup('Privileged');
} else {
- my $unpriv = RT::Group->new($self->CurrentUser);
- #$RT::Logger->debug("Making ".$self->Id." an unprivileged user");
- $unpriv->LoadSystemInternalGroup('Unprivileged');
- $unpriv->AddMember($self->PrincipalId);
+ $access_class->LoadSystemInternalGroup('Unprivileged');
+ }
+
+ unless ($access_class->id) {
+ $RT::Logger->crit("Could not load Privileged or Unprivileged group on user creation");
+ $RT::Handle->Rollback();
+ return ( 0, $self->loc('Could not create user') );
+ }
+
+
+ my ($ac_id, $ac_msg) = $access_class->_AddMember( InsideTransaction => 1, PrincipalId => $self->PrincipalId);
+
+ unless ($ac_id) {
+ $RT::Logger->crit("Could not add user to Privileged or Unprivileged group on user creation. Aborted");
+ $RT::Logger->crit($ac_msg);
+ $RT::Handle->Rollback();
+ return ( 0, $self->loc('Could not create user') );
}
- # $RT::Logger->debug("Finished creating the user");
+ $RT::Handle->Commit;
return ( $id, $self->loc('User created') );
}
my $self = shift;
my $val = shift;
+ #Check the ACL
+ unless ( $self->CurrentUser->HasRight(Right => 'AdminUsers', Object => $RT::System) ) {
+ return ( 0, $self->loc('Permission Denied') );
+ }
my $priv = RT::Group->new($self->CurrentUser);
$priv->LoadSystemInternalGroup('Privileged');
return (0,$self->loc("That user is already privileged"));
}
if ($unpriv->HasMember($self->PrincipalObj)) {
- $unpriv->DeleteMember($self->PrincipalId);
+ $unpriv->_DeleteMember($self->PrincipalId);
} else {
# if we had layered transactions, life would be good
# sadly, we have to just go ahead, even if something
$RT::Logger->crit("User ".$self->Id." is neither privileged nor ".
"unprivileged. something is drastically wrong.");
}
- my ($status, $msg) = $priv->AddMember($self->PrincipalId);
+ my ($status, $msg) = $priv->_AddMember( InsideTransaction => 1, PrincipalId => $self->PrincipalId);
if ($status) {
return (1, $self->loc("That user is now privileged"));
} else {
return (0,$self->loc("That user is already unprivileged"));
}
if ($priv->HasMember($self->PrincipalObj)) {
- $priv->DeleteMember($self->PrincipalId);
+ $priv->_DeleteMember( $self->PrincipalId);
} else {
# if we had layered transactions, life would be good
# sadly, we have to just go ahead, even if something
$RT::Logger->crit("User ".$self->Id." is neither privileged nor ".
"unprivileged. something is drastically wrong.");
}
- my ($status, $msg) = $unpriv->AddMember($self->PrincipalId);
+ my ($status, $msg) = $unpriv->_AddMember( InsideTransaction => 1, PrincipalId => $self->PrincipalId);
if ($status) {
return (1, $self->loc("That user is now unprivileged"));
} else {
my ($val, $message);
+ my ( $Address, $Name ) =
+ RT::EmailParser::ParseAddressFromHeader('', $email);
+ $email = $Address;
+
$self->LoadByEmail($email);
$message = $self->loc('User loaded');
unless ($self->Id) {
( $val, $message ) = $self->Create(
Name => $email,
EmailAddress => $email,
- RealName => $email,
+ RealName => $Name,
Privileged => 0,
Comments => 'Autocreated when added as a watcher');
unless ($val) {
# }}}
+# {{{ sub CanonicalizeUserInfo
+
+
+
+=item CanonicalizeUserInfo HASH of ARGS
+
+# CanonicalizeUserInfo can convert all User->Create options.
+# it takes a hashref of all the params sent to User->Create and
+# returns that same hash, by default nothing is done.
+
+# This function is intended to allow users to have their info looked up via
+# an outside source and modified upon creation.
+
+=cut
+
+sub CanonicalizeUserInfo {
+ my $self = shift;
+ my $args = shift;
+ my $success = 1;
+
+ return ($success);
+}
+
+
+# }}}
+
# {{{ Password related functions
my $template = RT::Template->new( $self->CurrentUser );
- if ( $self->IsPrivileged ) {
+ if ( $self->Privileged ) {
$template->LoadGlobalTemplate('RT_PasswordChange_Privileged');
}
else {
Argument => $pass
);
- $notification->SetTo( $self->EmailAddress );
+ $notification->SetHeader( 'To', $self->EmailAddress );
my ($ret);
$ret = $notification->Prepare();
my $length = $min_length + int( rand( $max_length - $min_length ) );
- my $char = $self->GenerateRandomNextChar( $total_sum, $start_freq );
+ my $char = $self->_GenerateRandomNextChar( $total_sum, $start_freq );
my @word = ( $char + $a );
for ( 2 .. $length ) {
$char =