From 3ef62a0570055da710328937e7f65dbb2c027c62 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 Aug 2002 06:17:09 +0000 Subject: import rt 2.0.14 --- rt/lib/RT/User.pm | 1222 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1222 insertions(+) create mode 100755 rt/lib/RT/User.pm (limited to 'rt/lib/RT/User.pm') diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm new file mode 100755 index 000000000..4e8554030 --- /dev/null +++ b/rt/lib/RT/User.pm @@ -0,0 +1,1222 @@ +# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/User.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +# (c) 1996-2000 Jesse Vincent +# This software is redistributable under the terms of the GNU GPL + +=head1 NAME + + RT::User - RT User object + +=head1 SYNOPSIS + + use RT::User; + +=head1 DESCRIPTION + + +=head1 METHODS + +=begin testing + +ok(require RT::TestHarness); +ok(require RT::User); + +=end testing + + +=cut + + +package RT::User; +use RT::Record; +@ISA= qw(RT::Record); + +# {{{ sub _Init +sub _Init { + my $self = shift; + $self->{'table'} = "Users"; + return($self->SUPER::_Init(@_)); +} +# }}} + +# {{{ sub _Accessible + +sub _Accessible { + my $self = shift; + my %Cols = ( + # {{{ Core RT info + Name => 'public/read/write/admin', + Password => 'write', + Comments => 'read/write/admin', + Signature => 'read/write', + EmailAddress => 'public/read/write', + PagerEmailAddress => 'read/write', + FreeformContactInfo => 'read/write', + Organization => 'public/read/write/admin', + Disabled => 'public/read/write/admin', #To modify this attribute, we have helper + #methods + Privileged => 'read/write/admin', # 0=no 1=user 2=system + + # }}} + + # {{{ Names + + RealName => 'public/read/write', + NickName => 'public/read/write', + # }}} + + # {{{ Localization and Internationalization + Lang => 'public/read/write', + EmailEncoding => 'public/read/write', + WebEncoding => 'public/read/write', + # }}} + + # {{{ External ContactInfo Linkage + ExternalContactInfoId => 'public/read/write/admin', + ContactInfoSystem => 'public/read/write/admin', + # }}} + + # {{{ User Authentication identifier + ExternalAuthId => 'public/read/write/admin', + #Authentication system used for user + AuthSystem => 'public/read/write/admin', + Gecos => 'public/read/write/admin', #Gecos is the name of the fields in a + # unix passwd file. In this case, it refers to "Unix Username" + # }}} + + # {{{ Telephone numbers + HomePhone => 'read/write', + WorkPhone => 'read/write', + MobilePhone => 'read/write', + PagerPhone => 'read/write', + + # }}} + + # {{{ Paper Address + Address1 => 'read/write', + Address2 => 'read/write', + City => 'read/write', + State => 'read/write', + Zip => 'read/write', + Country => 'read/write', + # }}} + + # {{{ Core DBIx::Record Attributes + Creator => 'read/auto', + Created => 'read/auto', + LastUpdatedBy => 'read/auto', + LastUpdated => 'read/auto' + + # }}} + ); + return($self->SUPER::_Accessible(@_, %Cols)); +} + +# }}} + +# {{{ sub Create + +sub Create { + my $self = shift; + my %args = (Privileged => 0, + @_ # get the real argumentlist + ); + + #Check the ACL + unless ($self->CurrentUserHasRight('AdminUsers')) { + return (0, 'No permission to create users'); + } + + if (! $args{'Password'}) { + $args{'Password'} = '*NO-PASSWORD*'; + } + elsif (length($args{'Password'}) < $RT::MinimumPasswordLength) { + return(0,"Password too short"); + } + else { + my $salt = join '', ('.','/',0..9,'A'..'Z','a'..'z')[rand 64, rand 64]; + $args{'Password'} = crypt($args{'Password'}, $salt); + } + + + #TODO Specify some sensible defaults. + + unless (defined ($args{'Name'})) { + return(0, "Must specify 'Name' attribute"); + } + + + #SANITY CHECK THE NAME AND ABORT IF IT'S TAKEN + if ($RT::SystemUser) { #This only works if RT::SystemUser has been defined + my $TempUser = RT::User->new($RT::SystemUser); + $TempUser->Load($args{'Name'}); + return (0, 'Name in use') if ($TempUser->Id); + + return(0, 'Email address in use') + unless ($self->ValidateEmailAddress($args{'EmailAddress'})); + } + else { + $RT::Logger->warning("$self couldn't check for pre-existing ". + " users on create. This will happen". + " on installation\n"); + } + + my $id = $self->SUPER::Create(%args); + + #If the create failed. + unless ($id) { + return (0, '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" + #} + + return ($id, 'User created'); +} + +# }}} + +# {{{ sub _BootstrapCreate + +#create a user without validating _any_ data. + +#To be used only on database init. + +sub _BootstrapCreate { + my $self = shift; + my %args = (@_); + + $args{'Password'} = "*NO-PASSWORD*"; + my $id = $self->SUPER::Create(%args); + + #If the create failed. + return (0, 'Could not create user') + unless ($id); + + return ($id, 'User created'); +} + +# }}} + +# {{{ sub Delete + +sub Delete { + my $self = shift; + + return(0, 'Deleting this object would violate referential integrity'); + +} + +# }}} + +# {{{ sub Load + +=head2 Load + +Load a user object from the database. Takes a single argument. +If the argument is numerical, load by the column 'id'. Otherwise, load by +the "Name" column which is the user's textual username. + +=cut + +sub Load { + my $self = shift; + my $identifier = shift || return undef; + + #if it's an int, load by id. otherwise, load by name. + if ($identifier !~ /\D/) { + $self->SUPER::LoadById($identifier); + } + else { + $self->LoadByCol("Name",$identifier); + } +} + +# }}} + + +# {{{ sub LoadByEmail + +=head2 LoadByEmail + +Tries to load this user object from the database by the user's email address. + + +=cut + +sub LoadByEmail { + my $self=shift; + my $address = shift; + + # Never load an empty address as an email address. + unless ($address) { + return(undef); + } + + $address = RT::CanonicalizeAddress($address); + #$RT::Logger->debug("Trying to load an email address: $address\n"); + return $self->LoadByCol("EmailAddress", $address); +} +# }}} + + +# {{{ sub ValidateEmailAddress + +=head2 ValidateEmailAddress ADDRESS + +Returns true if the email address entered is not in use by another user or is +undef or ''. Returns false if it's in use. + +=cut + +sub ValidateEmailAddress { + my $self = shift; + my $Value = shift; + + # if the email address is null, it's always valid + return (1) if(!$Value || $Value eq ""); + + my $TempUser = RT::User->new($RT::SystemUser); + $TempUser->LoadByEmail($Value); + + if( $TempUser->id && + ($TempUser->id != $self->id)) { # if we found a user with that address + # it's invalid to set this user's address to it + return(undef); + } + else { #it's a valid email address + return(1); + } +} + +# }}} + + + + +# {{{ sub SetRandomPassword + +=head2 SetRandomPassword + +Takes no arguments. Returns a status code and a new password or an error message. +If the status is 1, the second value returned is the new password. +If the status is anything else, the new value returned is the error code. + +=cut + +sub SetRandomPassword { + my $self = shift; + + + unless ($self->CurrentUserCanModify('Password')) { + return (0, "Permission Denied"); + } + + my $pass = $self->GenerateRandomPassword(6,8); + + # If we have "notify user on + + my ($val, $msg) = $self->SetPassword($pass); + + #If we got an error return the error. + return (0, $msg) unless ($val); + + #Otherwise, we changed the password, lets return it. + return (1, $pass); + +} + +# }}} + + +# {{{ sub ResetPassword + +=head2 ResetPassword + +Returns status, [ERROR or new password]. Resets this user\'s password to +a randomly generated pronouncable password and emails them, using a +global template called "RT_PasswordChange", which can be overridden +with global templates "RT_PasswordChange_Privileged" or "RT_PasswordChange_NonPrivileged" +for privileged and Non-privileged users respectively. + +=cut + +sub ResetPassword { + my $self = shift; + + unless ($self->CurrentUserCanModify('Password')) { + return (0, "Permission Denied"); + } + my ($status, $pass) = $self->SetRandomPassword(); + + unless ($status) { + return (0, "$pass"); + } + + my $template = RT::Template->new($self->CurrentUser); + + + if ($self->IsPrivileged) { + $template->LoadGlobalTemplate('RT_PasswordChange_Privileged'); + } + else { + $template->LoadGlobalTemplate('RT_PasswordChange_Privileged'); + } + + unless ($template->Id) { + $template->LoadGlobalTemplate('RT_PasswordChange'); + } + + unless ($template->Id) { + $RT::Logger->crit("$self tried to send ".$self->Name." a password reminder ". + "but couldn't find a password change template"); + } + + my $notification = RT::Action::SendPasswordEmail->new(TemplateObj => $template, + Argument => $pass); + + $notification->SetTo($self->EmailAddress); + + my ($ret); + $ret = $notification->Prepare(); + if ($ret) { + $ret = $notification->Commit(); + } + + if ($ret) { + return(1, 'New password notification sent'); + } else { + return (0, 'Notification could not be sent'); + } + +} + + +# }}} + +# {{{ sub GenerateRandomPassword + +=head2 GenerateRandomPassword MIN_LEN and MAX_LEN + +Returns a random password between MIN_LEN and MAX_LEN characters long. + +=cut + +sub GenerateRandomPassword { + my $self = shift; + my $min_length = shift; + my $max_length = shift; + + #This code derived from mpw.pl, a bit of code with a sordid history + # Its notes: + + # Perl cleaned up a bit by Jesse Vincent 1/14/2001. + # Converted to perl from C by Marc Horowitz, 1/20/2000. + # Converted to C from Multics PL/I by Bill Sommerfeld, 4/21/86. + # Original PL/I version provided by Jerry Saltzer. + + + my ($frequency, $start_freq, $total_sum, $row_sums); + + #When munging characters, we need to know where to start counting letters from + my $a = ord('a'); + + # frequency of English digraphs (from D Edwards 1/27/66) + $frequency = + [ [ 4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, + 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1, 9, 1 ], # aa - az + [ 13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, + 0, 11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0 ], # ba - bz + [ 32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, + 0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0 ], # ca - cz + [ 40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, + 6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0 ], # da - dz + [ 84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, 55, 54, + 146, 35, 37, 6, 191, 149, 65, 9, 26, 21, 12, 5, 0 ], # ea - ez + [ 19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, + 0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0 ], # fa - fz + [ 20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, + 4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0 ], # ga - gz + [ 101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, + 2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0 ], # ha - hz + [ 40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, 25, + 202, 56, 12, 1, 46, 79, 117, 1, 22, 0, 4, 0, 3 ], # ia - iz + [ 3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 ], # ja - jz + [ 1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0 ], # ka - kz + [ 44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, + 2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0 ], # la - lz + [ 52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, + 1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0 ], # ma - mz + [ 42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, 6, 9, + 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0, 12, 0 ], # na - nz + [ 7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, 41, + 134, 13, 23, 0, 91, 23, 42, 55, 16, 28, 0, 4, 1 ], # oa - oz + [ 19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, + 0, 27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0 ], # pa - pz + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0 ], # qa - qz + [ 83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, + 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0, 28, 0 ], # ra - rz + [ 65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, 11, + 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0, 4, 0 ], # sa - sz + [ 57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, 10, + 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0, 24, 0 ], # ta - tz + [ 11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, + 31, 1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0 ], # ua - uz + [ 7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ], # va - vz + [ 36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, + 8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0 ], # wa - wz + [ 1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, + 0, 1, 5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0 ], # xa - xz + [ 14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, + 5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0 ], # ya - yz + [ 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ]; # za - zz + + #We need to know the totals for each row + $row_sums = + [ map { my $sum = 0; map { $sum += $_ } @$_; $sum } @$frequency ]; + + + #Frequency with which a given letter starts a word. + $start_freq = + [ 1299, 425, 725, 271, 375, 470, 93, 223, 1009, 24, 20, 355, 379, + 319, 823, 618, 21, 317, 962, 1991, 271, 104, 516, 6, 16, 14 ]; + + $total_sum = 0; map { $total_sum += $_ } @$start_freq; + + + my $length = $min_length + int(rand($max_length-$min_length)); + + my $char = $self->GenerateRandomNextChar($total_sum, $start_freq); + my @word = ($char+$a); + for (2..$length) { + $char = $self->_GenerateRandomNextChar($row_sums->[$char], $frequency->[$char]); + push(@word, $char+$a); + } + + #Return the password + return pack("C*",@word); + +} + + +#A private helper function for RandomPassword +# Takes a row summary and a frequency chart for the next character to be searched +sub _GenerateRandomNextChar { + my $self = shift; + my($all, $freq) = @_; + my($pos, $i); + + for ($pos = int(rand($all)), $i=0; + $pos >= $freq->[$i]; + $pos -= $freq->[$i], $i++) {}; + + return($i); +} + +# }}} + +# {{{ sub SetPassword + +=head2 SetPassword + +Takes a string. Checks the string's length and sets this user's password +to that string. + +=cut + +sub SetPassword { + my $self = shift; + my $password = shift; + + unless ($self->CurrentUserCanModify('Password')) { + return(0, 'Permission Denied'); + } + + if (! $password) { + return(0, "No password set"); + } + elsif (length($password) < $RT::MinimumPasswordLength) { + return(0,"Password too short"); + } + else { + my $salt = join '', ('.','/',0..9,'A'..'Z','a'..'z')[rand 64, rand 64]; + return ( $self->SUPER::SetPassword(crypt($password, $salt)) ); + } + +} + +# }}} + +# {{{ sub IsPassword + +=head2 IsPassword + +Returns true if the passed in value is this user's password. +Returns undef otherwise. + +=cut + +sub IsPassword { + my $self = shift; + my $value = shift; + + #TODO there isn't any apparent way to legitimately ACL this + + # RT does not allow null passwords + if ((!defined ($value)) or ($value eq '')) { + return(undef); + } + if ($self->Disabled) { + $RT::Logger->info("Disabled user ".$self->Name." tried to log in"); + return(undef); + } + + if ( ($self->__Value('Password') eq '') || + ($self->__Value('Password') eq undef) ) { + return(undef); + } + if ($self->__Value('Password') eq crypt($value, $self->__Value('Password'))) { + return (1); + } + else { + return (undef); + } +} + +# }}} + +# {{{ sub SetDisabled + +=head2 Sub SetDisabled + +Toggles the user's disabled flag. +If this flag is +set, all password checks for this user will fail. All ACL checks for this +user will fail. The user will appear in no user listings. + +=cut + +# }}} + +# {{{ ACL Related routines + +# {{{ GrantQueueRight + +=head2 GrantQueueRight + +Grant a queue right to this user. Takes a paramhash of which the elements +RightAppliesTo and RightName are important. + +=cut + +sub GrantQueueRight { + + my $self = shift; + my %args = ( RightScope => 'Queue', + RightName => undef, + RightAppliesTo => undef, + PrincipalType => 'User', + PrincipalId => $self->Id, + @_); + + #ACL check handled in ACE.pm + + require RT::ACE; + +# $RT::Logger->debug("$self ->GrantQueueRight right:". $args{'RightName'} . +# " applies to queue ".$args{'RightAppliesTo'}."\n"); + + my $ace = new RT::ACE($self->CurrentUser); + + return ($ace->Create(%args)); +} + +# }}} + +# {{{ GrantSystemRight + +=head2 GrantSystemRight + +Grant a system right to this user. +The only element that's important to set is RightName. + +=cut +sub GrantSystemRight { + + my $self = shift; + my %args = ( RightScope => 'System', + RightName => undef, + RightAppliesTo => 0, + PrincipalType => 'User', + PrincipalId => $self->Id, + @_); + + + #ACL check handled in ACE.pm + + require RT::ACE; + my $ace = new RT::ACE($self->CurrentUser); + + return ($ace->Create(%args)); +} + + +# }}} + +# {{{ sub HasQueueRight + +=head2 HasQueueRight + +Takes a paramhash which can contain +these items: + TicketObj => RT::Ticket or QueueObj => RT::Queue or Queue => integer + IsRequestor => undef, (for bootstrapping create) + Right => 'Right' + + +Returns 1 if this user has the right specified in the paramhash. for the queue +passed in. + +Returns undef if they don't + +=cut + +sub HasQueueRight { + my $self = shift; + my %args = ( TicketObj => undef, + QueueObj => undef, + Queue => undef, + IsRequestor => undef, + Right => undef, + @_); + + my ($IsRequestor, $IsCc, $IsAdminCc, $IsOwner); + + if (defined $args{'Queue'}) { + $args{'QueueObj'} = new RT::Queue($self->CurrentUser); + $args{'QueueObj'}->Load($args{'Queue'}); + } + + if (defined $args{'TicketObj'}) { + $args{'QueueObj'} = $args{'TicketObj'}->QueueObj(); + } + + # {{{ Validate and load up the QueueId + unless ((defined $args{'QueueObj'}) and ($args{'QueueObj'}->Id)) { + require Carp; + $RT::Logger->debug(Carp::cluck ("$self->HasQueueRight Couldn't find a queue id")); + return undef; + } + + # }}} + + + # Figure out whether a user has the right we're asking about. + # first see if they have the right personally for the queue in question. + my $retval = $self->_HasRight(Scope => 'Queue', + AppliesTo => $args{'QueueObj'}->Id, + Right => $args{'Right'}, + IsOwner => $IsOwner); + + return ($retval) if (defined $retval); + + # then we see whether they have the right personally globally. + $retval = $self->HasSystemRight( $args{'Right'}); + + return ($retval) if (defined $retval); + + # now that we know they don't have the right personally, + + # {{{ Find out about whether the current user is a Requestor, Cc, AdminCc or Owner + + if (defined $args{'TicketObj'}) { + if ($args{'TicketObj'}->IsRequestor($self)) {#user is requestor + $IsRequestor = 1; + } + + if ($args{'TicketObj'}->IsCc($self)) { #If user is a cc + $IsCc = 1; + } + + if ($args{'TicketObj'}->IsAdminCc($self)) { #If user is an admin cc + $IsAdminCc = 1; + } + + if ($args{'TicketObj'}->IsOwner($self)) { #If user is an owner + $IsOwner = 1; + } + } + + if (defined $args{'QueueObj'}) { + if ($args{'QueueObj'}->IsCc($self)) { #If user is a cc + $IsCc = 1; + } + if ($args{'QueueObj'}->IsAdminCc($self)) { #If user is an admin cc + $IsAdminCc = 1; + } + + } + # }}} + + # then see whether they have the right for the queue as a member of a metagroup + + $retval = $self->_HasRight(Scope => 'Queue', + AppliesTo => $args{'QueueObj'}->Id, + Right => $args{'Right'}, + IsOwner => $IsOwner, + IsCc => $IsCc, + IsAdminCc => $IsAdminCc, + IsRequestor => $IsRequestor + ); + + return ($retval) if (defined $retval); + + # then we see whether they have the right globally as a member of a metagroup + $retval = $self->HasSystemRight( $args{'Right'}, + (IsOwner => $IsOwner, + IsCc => $IsCc, + IsAdminCc => $IsAdminCc, + IsRequestor => $IsRequestor + ) ); + + #If they haven't gotten it by now, they just lose. + return ($retval); + +} + +# }}} + +# {{{ sub HasSystemRight + +=head2 HasSystemRight + +takes an array of a single value and a paramhash. +The single argument is the right being passed in. +the param hash is some additional data. (IsCc, IsOwner, IsAdminCc and IsRequestor) + +Returns 1 if this user has the listed 'right'. Returns undef if this user doesn't. + +=cut + +sub HasSystemRight { + my $self = shift; + my $right = shift; + + my %args = ( IsOwner => undef, + IsCc => undef, + IsAdminCc => undef, + IsRequestor => undef, + @_); + + unless (defined $right) { + + $RT::Logger->debug("$self RT::User::HasSystemRight was passed in no right."); + return(undef); + } + return ( $self->_HasRight ( Scope => 'System', + AppliesTo => '0', + Right => $right, + IsOwner => $args{'IsOwner'}, + IsCc => $args{'IsCc'}, + IsAdminCc => $args{'IsAdminCc'}, + IsRequestor => $args{'IsRequestor'}, + + ) + ); + +} + +# }}} + +# {{{ sub _HasRight + +=head2 sub _HasRight (Right => 'right', Scope => 'scope', AppliesTo => int, ExtendedPrincipals => SQL) + +_HasRight is a private helper method for checking a user's rights. It takes +several options: + +=item Right is a textual right name + +=item Scope is a textual scope name. (As of July these were Queue, Ticket and System + +=item AppliesTo is the numerical Id of the object identified in the scope. For tickets, this is the queue #. for queues, this is the queue # + +=item ExtendedPrincipals is an SQL select clause which assumes that the only +table in play is ACL. It's used by HasQueueRight to pass in which +metaprincipals apply. Actually, it's probably obsolete. TODO: remove it. + +Returns 1 if a matching ACE was found. + +Returns undef if no ACE was found. + +=cut + + +sub _HasRight { + + my $self = shift; + my %args = ( Right => undef, + Scope => undef, + AppliesTo => undef, + IsRequestor => undef, + IsCc => undef, + IsAdminCc => undef, + IsOwner => undef, + ExtendedPrincipals => undef, + @_); + + if ($self->Disabled) { + $RT::Logger->debug ("Disabled User: ".$self->Name. + " failed access check for ".$args{'Right'}. + " to object ".$args{'Scope'}."/". + $args{'AppliesTo'}."\n"); + return (undef); + } + + if (!defined $args{'Right'}) { + $RT::Logger->debug("_HasRight called without a right\n"); + return(undef); + } + elsif (!defined $args{'Scope'}) { + $RT::Logger->debug("_HasRight called without a scope\n"); + return(undef); + } + elsif (!defined $args{'AppliesTo'}) { + $RT::Logger->debug("_HasRight called without an AppliesTo object\n"); + return(undef); + } + + #If we've cached a win or loss for this lookup say so + + #TODO Security +++ check to make sure this is complete and right + + #Construct a hashkey to cache decisions in + my ($hashkey); + { #it's ugly, but we need to turn off warning, cuz we're joining nulls. + local $^W=0; + $hashkey =$self->Id .":". join(':',%args); + } + + # $RT::Logger->debug($hashkey."\n"); + + #Anything older than 10 seconds needs to be rechecked + my $cache_timeout = (time - 10); + + + if ((defined $self->{'rights'}{"$hashkey"}) && + ($self->{'rights'}{"$hashkey"} == 1 ) && + (defined $self->{'rights'}{"$hashkey"}{'set'} ) && + ($self->{'rights'}{"$hashkey"}{'set'} > $cache_timeout)) { +# $RT::Logger->debug("Cached ACL win for ". +# $args{'Right'}.$args{'Scope'}. +# $args{'AppliesTo'}."\n"); + return ($self->{'rights'}{"$hashkey"}); + } + elsif ((defined $self->{'rights'}{"$hashkey"}) && + ($self->{'rights'}{"$hashkey"} == -1) && + (defined $self->{'rights'}{"$hashkey"}{'set'}) && + ($self->{'rights'}{"$hashkey"}{'set'} > $cache_timeout)) { + +# $RT::Logger->debug("Cached ACL loss decision for ". +# $args{'Right'}.$args{'Scope'}. +# $args{'AppliesTo'}."\n"); + + return(undef); + } + + + my $RightClause = "(RightName = '$args{'Right'}')"; + my $ScopeClause = "(RightScope = '$args{'Scope'}')"; + + #If an AppliesTo was passed in, we should pay attention to it. + #otherwise, none is needed + + $ScopeClause = "($ScopeClause AND (RightAppliesTo = $args{'AppliesTo'}))" + if ($args{'AppliesTo'}); + + + # The generic principals clause looks for users with my id + # and Rights that apply to _everyone_ + my $PrincipalsClause = "((PrincipalType = 'User') AND (PrincipalId = ".$self->Id."))"; + + + # If the user is the superuser, grant them the damn right ;) + my $SuperUserClause = + "(RightName = 'SuperUser') AND (RightScope = 'System') AND (RightAppliesTo = 0)"; + + # If we've been passed in an extended principals clause, we should lump it + # on to the existing principals clause. it'll make life easier + if ($args{'ExtendedPrincipals'}) { + $PrincipalsClause = "(($PrincipalsClause) OR ". + "($args{'ExtendedPrincipalsClause'}))"; + } + + my $GroupPrincipalsClause = "((ACL.PrincipalType = 'Group') ". + "AND (ACL.PrincipalId = Groups.Id) AND (GroupMembers.GroupId = Groups.Id) ". + " AND (GroupMembers.UserId = ".$self->Id."))"; + + + + + # {{{ A bunch of magic statements that make the metagroups listed + # work. basically, we if the user falls into the right group, + # we add the type of ACL check needed + my (@MetaPrincipalsSubClauses, $MetaPrincipalsClause); + + #The user is always part of the 'Everyone' Group + push (@MetaPrincipalsSubClauses, "((Groups.Name = 'Everyone') AND + (PrincipalType = 'Group') AND + (Groups.Id = PrincipalId))"); + + if ($args{'IsAdminCc'}) { + push (@MetaPrincipalsSubClauses, "((Groups.Name = 'AdminCc') AND + (PrincipalType = 'Group') AND + (Groups.Id = PrincipalId))"); + } + if ($args{'IsCc'}) { + push (@MetaPrincipalsSubClauses, " ((Groups.Name = 'Cc') AND + (PrincipalType = 'Group') AND + (Groups.Id = PrincipalId))"); + } + if ($args{'IsRequestor'}) { + push (@MetaPrincipalsSubClauses, " ((Groups.Name = 'Requestor') AND + (PrincipalType = 'Group') AND + (Groups.Id = PrincipalId))"); + } + if ($args{'IsOwner'}) { + + push (@MetaPrincipalsSubClauses, " ((Groups.Name = 'Owner') AND + (PrincipalType = 'Group') AND + (Groups.Id = PrincipalId))"); + } + + # }}} + + my ($GroupRightsQuery, $MetaGroupRightsQuery, $IndividualRightsQuery, $hitcount); + + # {{{ If there are any metaprincipals to be checked + if (@MetaPrincipalsSubClauses) { + #chop off the leading or + #TODO redo this with an array and a join + $MetaPrincipalsClause = join (" OR ", @MetaPrincipalsSubClauses); + + $MetaGroupRightsQuery = "SELECT COUNT(ACL.id) FROM ACL, Groups". + " WHERE " . + " ($ScopeClause) AND ($RightClause) AND ($MetaPrincipalsClause)"; + + # {{{ deal with checking if the user has a right as a member of a metagroup + +# $RT::Logger->debug("Now Trying $MetaGroupRightsQuery\n"); + $hitcount = $self->_Handle->FetchResult($MetaGroupRightsQuery); + + #if there's a match, the right is granted + if ($hitcount) { + $self->{'rights'}{"$hashkey"}{'set'} = time; + $self->{'rights'}{"$hashkey"} = 1; + return (1); + } + +# $RT::Logger->debug("No ACL matched MetaGroups query: $MetaGroupRightsQuery\n"); + + # }}} + + } + # }}} + + # {{{ deal with checking if the user has a right as a member of a group + # This query checks to se whether the user has the right as a member of a + # group + $GroupRightsQuery = "SELECT COUNT(ACL.id) FROM ACL, GroupMembers, Groups". + " WHERE " . + " (((($ScopeClause) AND ($RightClause)) OR ($SuperUserClause)) ". + " AND ($GroupPrincipalsClause))"; + + # $RT::Logger->debug("Now Trying $GroupRightsQuery\n"); + $hitcount = $self->_Handle->FetchResult($GroupRightsQuery); + + #if there's a match, the right is granted + if ($hitcount) { + $self->{'rights'}{"$hashkey"}{'set'} = time; + $self->{'rights'}{"$hashkey"} = 1; + return (1); + } + +# $RT::Logger->debug("No ACL matched $GroupRightsQuery\n"); + + # }}} + + # {{{ Check to see whether the user has a right as an individual + + # This query checks to see whether the current user has the right directly + $IndividualRightsQuery = "SELECT COUNT(ACL.id) FROM ACL WHERE ". + " ((($ScopeClause) AND ($RightClause)) OR ($SuperUserClause)) " . + " AND ($PrincipalsClause)"; + + + $hitcount = $self->_Handle->FetchResult($IndividualRightsQuery); + + if ($hitcount) { + $self->{'rights'}{"$hashkey"}{'set'} = time; + $self->{'rights'}{"$hashkey"} = 1; + return (1); + } + # }}} + + else { #If the user just doesn't have the right + +# $RT::Logger->debug("No ACL matched $IndividualRightsQuery\n"); + + #If nothing matched, return 0. + $self->{'rights'}{"$hashkey"}{'set'} = time; + $self->{'rights'}{"$hashkey"} = -1; + + + return (undef); + } +} + +# }}} + +# {{{ sub CurrentUserCanModify + +=head2 CurrentUserCanModify RIGHT + +If the user has rights for this object, either because +he has 'AdminUsers' or (if he\'s trying to edit himself and the right isn\'t an +admin right) 'ModifySelf', return 1. otherwise, return undef. + +=cut + +sub CurrentUserCanModify { + my $self = shift; + my $right = shift; + + if ($self->CurrentUserHasRight('AdminUsers')) { + return (1); + } + #If the field is marked as an "administrators only" field, + # don\'t let the user touch it. + elsif ($self->_Accessible($right, 'admin')) { + return(undef); + } + + #If the current user is trying to modify themselves + elsif ( ($self->id == $self->CurrentUser->id) and + ($self->CurrentUserHasRight('ModifySelf'))) { + return(1); + } + + #If we don\'t have a good reason to grant them rights to modify + # by now, they lose + else { + return(undef); + } + +} + +# }}} + +# {{{ sub CurrentUserHasRight + +=head2 CurrentUserHasRight + + Takes a single argument. returns 1 if $Self->CurrentUser + has the requested right. returns undef otherwise + +=cut + +sub CurrentUserHasRight { + my $self = shift; + my $right = shift; + + return ($self->CurrentUser->HasSystemRight($right)); +} + +# }}} + + +# {{{ sub _Set + +sub _Set { + my $self = shift; + + my %args = (Field => undef, + Value => undef, + @_ + ); + + # Nobody is allowed to futz with RT_System or Nobody unless they + # want to change an email address. For 2.2, neither should have an email address + + if ($self->Privileged == 2) { + return (0, "Can not modify system users"); + } + unless ($self->CurrentUserCanModify($args{'Field'})) { + return (0, "Permission Denied"); + } + + + + #Set the new value + my ($ret, $msg)=$self->SUPER::_Set(Field => $args{'Field'}, + Value=> $args{'Value'}); + + return ($ret, $msg); +} + +# }}} + +# {{{ sub _Value + +=head2 _Value + +Takes the name of a table column. +Returns its value as a string, if the user passes an ACL check + +=cut + +sub _Value { + + my $self = shift; + my $field = shift; + + #If the current user doesn't have ACLs, don't let em at it. + + my @PublicFields = qw( Name EmailAddress Organization Disabled + RealName NickName Gecos ExternalAuthId + AuthSystem ExternalContactInfoId + ContactInfoSystem ); + + #if the field is public, return it. + if ($self->_Accessible($field, 'public')) { + return($self->SUPER::_Value($field)); + + } + #If the user wants to see their own values, let them + elsif ($self->CurrentUser->Id == $self->Id) { + return($self->SUPER::_Value($field)); + } + #If the user has the admin users right, return the field + elsif ($self->CurrentUserHasRight('AdminUsers')) { + return($self->SUPER::_Value($field)); + } + else { + return(undef); + } + + +} + +# }}} + +# }}} +1; + -- cgit v1.2.1 From 945721f48f74d5cfffef7c7cf3a3d6bc2521f5dd Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 15 Jul 2003 13:16:32 +0000 Subject: import of rt 3.0.4 --- rt/lib/RT/User.pm | 1696 +++++++++++++++++++++-------------------------------- 1 file changed, 664 insertions(+), 1032 deletions(-) (limited to 'rt/lib/RT/User.pm') diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm index 4e8554030..cbc10f5b4 100755 --- a/rt/lib/RT/User.pm +++ b/rt/lib/RT/User.pm @@ -1,1222 +1,854 @@ -# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/User.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ -# (c) 1996-2000 Jesse Vincent -# This software is redistributable under the terms of the GNU GPL +# BEGIN LICENSE BLOCK +# +# Copyright (c) 1996-2003 Jesse Vincent +# +# (Except where explictly superceded by other copyright notices) +# +# 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. +# +# 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. +# +# +# END LICENSE BLOCK +# Autogenerated by DBIx::SearchBuilder factory (by ) +# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. +# +# !! DO NOT EDIT THIS FILE !! +# + +use strict; + =head1 NAME - RT::User - RT User object +RT::User -=head1 SYNOPSIS - use RT::User; +=head1 SYNOPSIS =head1 DESCRIPTION - =head1 METHODS -=begin testing +=cut + +package RT::User; +use RT::Record; + + +use vars qw( @ISA ); +@ISA= qw( RT::Record ); + +sub _Init { + my $self = shift; + + $self->Table('Users'); + $self->SUPER::_Init(@_); +} -ok(require RT::TestHarness); -ok(require RT::User); -=end testing + +=item Create PARAMHASH + +Create takes a hash of values and creates a row in the database: + + varchar(200) 'Name'. + varchar(40) 'Password'. + blob 'Comments'. + blob 'Signature'. + varchar(120) 'EmailAddress'. + blob 'FreeformContactInfo'. + varchar(200) 'Organization'. + varchar(120) 'RealName'. + varchar(16) 'NickName'. + varchar(16) 'Lang'. + varchar(16) 'EmailEncoding'. + varchar(16) 'WebEncoding'. + varchar(100) 'ExternalContactInfoId'. + varchar(30) 'ContactInfoSystem'. + varchar(100) 'ExternalAuthId'. + varchar(30) 'AuthSystem'. + varchar(16) 'Gecos'. + varchar(30) 'HomePhone'. + varchar(30) 'WorkPhone'. + varchar(30) 'MobilePhone'. + varchar(30) 'PagerPhone'. + varchar(200) 'Address1'. + varchar(200) 'Address2'. + varchar(100) 'City'. + varchar(100) 'State'. + varchar(16) 'Zip'. + varchar(50) 'Country'. + varchar(50) 'Timezone'. + text 'PGPKey'. + =cut -package RT::User; -use RT::Record; -@ISA= qw(RT::Record); -# {{{ sub _Init -sub _Init { + +sub Create { my $self = shift; - $self->{'table'} = "Users"; - return($self->SUPER::_Init(@_)); -} -# }}} - -# {{{ sub _Accessible - -sub _Accessible { - my $self = shift; - my %Cols = ( - # {{{ Core RT info - Name => 'public/read/write/admin', - Password => 'write', - Comments => 'read/write/admin', - Signature => 'read/write', - EmailAddress => 'public/read/write', - PagerEmailAddress => 'read/write', - FreeformContactInfo => 'read/write', - Organization => 'public/read/write/admin', - Disabled => 'public/read/write/admin', #To modify this attribute, we have helper - #methods - Privileged => 'read/write/admin', # 0=no 1=user 2=system - - # }}} - - # {{{ Names - - RealName => 'public/read/write', - NickName => 'public/read/write', - # }}} - - # {{{ Localization and Internationalization - Lang => 'public/read/write', - EmailEncoding => 'public/read/write', - WebEncoding => 'public/read/write', - # }}} - - # {{{ External ContactInfo Linkage - ExternalContactInfoId => 'public/read/write/admin', - ContactInfoSystem => 'public/read/write/admin', - # }}} - - # {{{ User Authentication identifier - ExternalAuthId => 'public/read/write/admin', - #Authentication system used for user - AuthSystem => 'public/read/write/admin', - Gecos => 'public/read/write/admin', #Gecos is the name of the fields in a - # unix passwd file. In this case, it refers to "Unix Username" - # }}} - - # {{{ Telephone numbers - HomePhone => 'read/write', - WorkPhone => 'read/write', - MobilePhone => 'read/write', - PagerPhone => 'read/write', - - # }}} - - # {{{ Paper Address - Address1 => 'read/write', - Address2 => 'read/write', - City => 'read/write', - State => 'read/write', - Zip => 'read/write', - Country => 'read/write', - # }}} - - # {{{ Core DBIx::Record Attributes - Creator => 'read/auto', - Created => 'read/auto', - LastUpdatedBy => 'read/auto', - LastUpdated => 'read/auto' - - # }}} - ); - return($self->SUPER::_Accessible(@_, %Cols)); + my %args = ( + Name => '', + Password => '', + Comments => '', + Signature => '', + EmailAddress => '', + FreeformContactInfo => '', + Organization => '', + RealName => '', + NickName => '', + Lang => '', + EmailEncoding => '', + WebEncoding => '', + ExternalContactInfoId => '', + ContactInfoSystem => '', + ExternalAuthId => '', + AuthSystem => '', + Gecos => '', + HomePhone => '', + WorkPhone => '', + MobilePhone => '', + PagerPhone => '', + Address1 => '', + Address2 => '', + City => '', + State => '', + Zip => '', + Country => '', + Timezone => '', + PGPKey => '', + + @_); + $self->SUPER::Create( + Name => $args{'Name'}, + Password => $args{'Password'}, + Comments => $args{'Comments'}, + Signature => $args{'Signature'}, + EmailAddress => $args{'EmailAddress'}, + FreeformContactInfo => $args{'FreeformContactInfo'}, + Organization => $args{'Organization'}, + RealName => $args{'RealName'}, + NickName => $args{'NickName'}, + Lang => $args{'Lang'}, + EmailEncoding => $args{'EmailEncoding'}, + WebEncoding => $args{'WebEncoding'}, + ExternalContactInfoId => $args{'ExternalContactInfoId'}, + ContactInfoSystem => $args{'ContactInfoSystem'}, + ExternalAuthId => $args{'ExternalAuthId'}, + AuthSystem => $args{'AuthSystem'}, + Gecos => $args{'Gecos'}, + HomePhone => $args{'HomePhone'}, + WorkPhone => $args{'WorkPhone'}, + MobilePhone => $args{'MobilePhone'}, + PagerPhone => $args{'PagerPhone'}, + Address1 => $args{'Address1'}, + Address2 => $args{'Address2'}, + City => $args{'City'}, + State => $args{'State'}, + Zip => $args{'Zip'}, + Country => $args{'Country'}, + Timezone => $args{'Timezone'}, + PGPKey => $args{'PGPKey'}, +); + } -# }}} -# {{{ sub Create -sub Create { - my $self = shift; - my %args = (Privileged => 0, - @_ # get the real argumentlist - ); - - #Check the ACL - unless ($self->CurrentUserHasRight('AdminUsers')) { - return (0, 'No permission to create users'); - } - - if (! $args{'Password'}) { - $args{'Password'} = '*NO-PASSWORD*'; - } - elsif (length($args{'Password'}) < $RT::MinimumPasswordLength) { - return(0,"Password too short"); - } - else { - my $salt = join '', ('.','/',0..9,'A'..'Z','a'..'z')[rand 64, rand 64]; - $args{'Password'} = crypt($args{'Password'}, $salt); - } - - - #TODO Specify some sensible defaults. - - unless (defined ($args{'Name'})) { - return(0, "Must specify 'Name' attribute"); - } - - - #SANITY CHECK THE NAME AND ABORT IF IT'S TAKEN - if ($RT::SystemUser) { #This only works if RT::SystemUser has been defined - my $TempUser = RT::User->new($RT::SystemUser); - $TempUser->Load($args{'Name'}); - return (0, 'Name in use') if ($TempUser->Id); - - return(0, 'Email address in use') - unless ($self->ValidateEmailAddress($args{'EmailAddress'})); - } - else { - $RT::Logger->warning("$self couldn't check for pre-existing ". - " users on create. This will happen". - " on installation\n"); - } - - my $id = $self->SUPER::Create(%args); - - #If the create failed. - unless ($id) { - return (0, '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" - #} - - return ($id, 'User created'); -} +=item id -# }}} +Returns the current value of id. +(In the database, id is stored as int(11).) -# {{{ sub _BootstrapCreate -#create a user without validating _any_ data. +=cut -#To be used only on database init. -sub _BootstrapCreate { - my $self = shift; - my %args = (@_); +=item Name - $args{'Password'} = "*NO-PASSWORD*"; - my $id = $self->SUPER::Create(%args); - - #If the create failed. - return (0, 'Could not create user') - unless ($id); +Returns the current value of Name. +(In the database, Name is stored as varchar(200).) - return ($id, 'User created'); -} -# }}} -# {{{ sub Delete +=item SetName VALUE -sub Delete { - my $self = shift; - - return(0, 'Deleting this object would violate referential integrity'); - -} -# }}} +Set Name to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Name will be stored as a varchar(200).) + + +=cut + + +=item Password + +Returns the current value of Password. +(In the database, Password is stored as varchar(40).) -# {{{ sub Load -=head2 Load -Load a user object from the database. Takes a single argument. -If the argument is numerical, load by the column 'id'. Otherwise, load by -the "Name" column which is the user's textual username. +=item SetPassword VALUE + + +Set Password to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Password will be stored as a varchar(40).) + =cut -sub Load { - my $self = shift; - my $identifier = shift || return undef; - - #if it's an int, load by id. otherwise, load by name. - if ($identifier !~ /\D/) { - $self->SUPER::LoadById($identifier); - } - else { - $self->LoadByCol("Name",$identifier); - } -} -# }}} +=item Comments + +Returns the current value of Comments. +(In the database, Comments is stored as blob.) -# {{{ sub LoadByEmail -=head2 LoadByEmail +=item SetComments VALUE -Tries to load this user object from the database by the user's email address. + +Set Comments to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Comments will be stored as a blob.) =cut -sub LoadByEmail { - my $self=shift; - my $address = shift; - # Never load an empty address as an email address. - unless ($address) { - return(undef); - } +=item Signature - $address = RT::CanonicalizeAddress($address); - #$RT::Logger->debug("Trying to load an email address: $address\n"); - return $self->LoadByCol("EmailAddress", $address); -} -# }}} +Returns the current value of Signature. +(In the database, Signature is stored as blob.) -# {{{ sub ValidateEmailAddress -=head2 ValidateEmailAddress ADDRESS +=item SetSignature VALUE + + +Set Signature to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Signature will be stored as a blob.) -Returns true if the email address entered is not in use by another user or is -undef or ''. Returns false if it's in use. =cut -sub ValidateEmailAddress { - my $self = shift; - my $Value = shift; - # if the email address is null, it's always valid - return (1) if(!$Value || $Value eq ""); +=item EmailAddress - my $TempUser = RT::User->new($RT::SystemUser); - $TempUser->LoadByEmail($Value); +Returns the current value of EmailAddress. +(In the database, EmailAddress is stored as varchar(120).) - if( $TempUser->id && - ($TempUser->id != $self->id)) { # if we found a user with that address - # it's invalid to set this user's address to it - return(undef); - } - else { #it's a valid email address - return(1); - } -} -# }}} +=item SetEmailAddress VALUE + + +Set EmailAddress to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, EmailAddress will be stored as a varchar(120).) + + +=cut + + +=item FreeformContactInfo + +Returns the current value of FreeformContactInfo. +(In the database, FreeformContactInfo is stored as blob.) -# {{{ sub SetRandomPassword +=item SetFreeformContactInfo VALUE -=head2 SetRandomPassword -Takes no arguments. Returns a status code and a new password or an error message. -If the status is 1, the second value returned is the new password. -If the status is anything else, the new value returned is the error code. +Set FreeformContactInfo to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, FreeformContactInfo will be stored as a blob.) + =cut -sub SetRandomPassword { - my $self = shift; +=item Organization - unless ($self->CurrentUserCanModify('Password')) { - return (0, "Permission Denied"); - } - - my $pass = $self->GenerateRandomPassword(6,8); +Returns the current value of Organization. +(In the database, Organization is stored as varchar(200).) - # If we have "notify user on - my ($val, $msg) = $self->SetPassword($pass); - - #If we got an error return the error. - return (0, $msg) unless ($val); - - #Otherwise, we changed the password, lets return it. - return (1, $pass); - -} -# }}} +=item SetOrganization VALUE + + +Set Organization to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Organization will be stored as a varchar(200).) + + +=cut + + +=item RealName + +Returns the current value of RealName. +(In the database, RealName is stored as varchar(120).) -# {{{ sub ResetPassword -=head2 ResetPassword +=item SetRealName VALUE + + +Set RealName to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, RealName will be stored as a varchar(120).) -Returns status, [ERROR or new password]. Resets this user\'s password to -a randomly generated pronouncable password and emails them, using a -global template called "RT_PasswordChange", which can be overridden -with global templates "RT_PasswordChange_Privileged" or "RT_PasswordChange_NonPrivileged" -for privileged and Non-privileged users respectively. =cut -sub ResetPassword { - my $self = shift; - - unless ($self->CurrentUserCanModify('Password')) { - return (0, "Permission Denied"); - } - my ($status, $pass) = $self->SetRandomPassword(); - - unless ($status) { - return (0, "$pass"); - } - - my $template = RT::Template->new($self->CurrentUser); - - - if ($self->IsPrivileged) { - $template->LoadGlobalTemplate('RT_PasswordChange_Privileged'); - } - else { - $template->LoadGlobalTemplate('RT_PasswordChange_Privileged'); - } - - unless ($template->Id) { - $template->LoadGlobalTemplate('RT_PasswordChange'); - } - - unless ($template->Id) { - $RT::Logger->crit("$self tried to send ".$self->Name." a password reminder ". - "but couldn't find a password change template"); - } - - my $notification = RT::Action::SendPasswordEmail->new(TemplateObj => $template, - Argument => $pass); - - $notification->SetTo($self->EmailAddress); - - my ($ret); - $ret = $notification->Prepare(); - if ($ret) { - $ret = $notification->Commit(); - } - - if ($ret) { - return(1, 'New password notification sent'); - } else { - return (0, 'Notification could not be sent'); - } - -} +=item NickName -# }}} +Returns the current value of NickName. +(In the database, NickName is stored as varchar(16).) -# {{{ sub GenerateRandomPassword -=head2 GenerateRandomPassword MIN_LEN and MAX_LEN -Returns a random password between MIN_LEN and MAX_LEN characters long. +=item SetNickName VALUE + + +Set NickName to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, NickName will be stored as a varchar(16).) + =cut -sub GenerateRandomPassword { - my $self = shift; - my $min_length = shift; - my $max_length = shift; - - #This code derived from mpw.pl, a bit of code with a sordid history - # Its notes: - - # Perl cleaned up a bit by Jesse Vincent 1/14/2001. - # Converted to perl from C by Marc Horowitz, 1/20/2000. - # Converted to C from Multics PL/I by Bill Sommerfeld, 4/21/86. - # Original PL/I version provided by Jerry Saltzer. - - - my ($frequency, $start_freq, $total_sum, $row_sums); - - #When munging characters, we need to know where to start counting letters from - my $a = ord('a'); - - # frequency of English digraphs (from D Edwards 1/27/66) - $frequency = - [ [ 4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, - 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1, 9, 1 ], # aa - az - [ 13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, - 0, 11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0 ], # ba - bz - [ 32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, - 0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0 ], # ca - cz - [ 40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, - 6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0 ], # da - dz - [ 84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, 55, 54, - 146, 35, 37, 6, 191, 149, 65, 9, 26, 21, 12, 5, 0 ], # ea - ez - [ 19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, - 0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0 ], # fa - fz - [ 20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, - 4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0 ], # ga - gz - [ 101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, - 2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0 ], # ha - hz - [ 40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, 25, - 202, 56, 12, 1, 46, 79, 117, 1, 22, 0, 4, 0, 3 ], # ia - iz - [ 3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 ], # ja - jz - [ 1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0 ], # ka - kz - [ 44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, - 2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0 ], # la - lz - [ 52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, - 1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0 ], # ma - mz - [ 42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, 6, 9, - 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0, 12, 0 ], # na - nz - [ 7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, 41, - 134, 13, 23, 0, 91, 23, 42, 55, 16, 28, 0, 4, 1 ], # oa - oz - [ 19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, - 0, 27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0 ], # pa - pz - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0 ], # qa - qz - [ 83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, - 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0, 28, 0 ], # ra - rz - [ 65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, 11, - 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0, 4, 0 ], # sa - sz - [ 57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, 10, - 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0, 24, 0 ], # ta - tz - [ 11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, - 31, 1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0 ], # ua - uz - [ 7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, - 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 ], # va - vz - [ 36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, - 8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0 ], # wa - wz - [ 1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, - 0, 1, 5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0 ], # xa - xz - [ 14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, - 5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0 ], # ya - yz - [ 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ]; # za - zz - - #We need to know the totals for each row - $row_sums = - [ map { my $sum = 0; map { $sum += $_ } @$_; $sum } @$frequency ]; - - - #Frequency with which a given letter starts a word. - $start_freq = - [ 1299, 425, 725, 271, 375, 470, 93, 223, 1009, 24, 20, 355, 379, - 319, 823, 618, 21, 317, 962, 1991, 271, 104, 516, 6, 16, 14 ]; - - $total_sum = 0; map { $total_sum += $_ } @$start_freq; - - - my $length = $min_length + int(rand($max_length-$min_length)); - - my $char = $self->GenerateRandomNextChar($total_sum, $start_freq); - my @word = ($char+$a); - for (2..$length) { - $char = $self->_GenerateRandomNextChar($row_sums->[$char], $frequency->[$char]); - push(@word, $char+$a); - } - - #Return the password - return pack("C*",@word); - -} +=item Lang + +Returns the current value of Lang. +(In the database, Lang is stored as varchar(16).) -#A private helper function for RandomPassword -# Takes a row summary and a frequency chart for the next character to be searched -sub _GenerateRandomNextChar { - my $self = shift; - my($all, $freq) = @_; - my($pos, $i); - - for ($pos = int(rand($all)), $i=0; - $pos >= $freq->[$i]; - $pos -= $freq->[$i], $i++) {}; - - return($i); -} -# }}} -# {{{ sub SetPassword +=item SetLang VALUE -=head2 SetPassword -Takes a string. Checks the string's length and sets this user's password -to that string. +Set Lang to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Lang will be stored as a varchar(16).) + =cut -sub SetPassword { - my $self = shift; - my $password = shift; - - unless ($self->CurrentUserCanModify('Password')) { - return(0, 'Permission Denied'); - } - - if (! $password) { - return(0, "No password set"); - } - elsif (length($password) < $RT::MinimumPasswordLength) { - return(0,"Password too short"); - } - else { - my $salt = join '', ('.','/',0..9,'A'..'Z','a'..'z')[rand 64, rand 64]; - return ( $self->SUPER::SetPassword(crypt($password, $salt)) ); - } - -} -# }}} +=item EmailEncoding + +Returns the current value of EmailEncoding. +(In the database, EmailEncoding is stored as varchar(16).) -# {{{ sub IsPassword -=head2 IsPassword -Returns true if the passed in value is this user's password. -Returns undef otherwise. +=item SetEmailEncoding VALUE + + +Set EmailEncoding to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, EmailEncoding will be stored as a varchar(16).) + =cut -sub IsPassword { - my $self = shift; - my $value = shift; - - #TODO there isn't any apparent way to legitimately ACL this - - # RT does not allow null passwords - if ((!defined ($value)) or ($value eq '')) { - return(undef); - } - if ($self->Disabled) { - $RT::Logger->info("Disabled user ".$self->Name." tried to log in"); - return(undef); - } - - if ( ($self->__Value('Password') eq '') || - ($self->__Value('Password') eq undef) ) { - return(undef); - } - if ($self->__Value('Password') eq crypt($value, $self->__Value('Password'))) { - return (1); - } - else { - return (undef); - } -} -# }}} +=item WebEncoding + +Returns the current value of WebEncoding. +(In the database, WebEncoding is stored as varchar(16).) -# {{{ sub SetDisabled -=head2 Sub SetDisabled -Toggles the user's disabled flag. -If this flag is -set, all password checks for this user will fail. All ACL checks for this -user will fail. The user will appear in no user listings. +=item SetWebEncoding VALUE -=cut -# }}} +Set WebEncoding to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, WebEncoding will be stored as a varchar(16).) -# {{{ ACL Related routines -# {{{ GrantQueueRight +=cut + -=head2 GrantQueueRight +=item ExternalContactInfoId + +Returns the current value of ExternalContactInfoId. +(In the database, ExternalContactInfoId is stored as varchar(100).) + + + +=item SetExternalContactInfoId VALUE + + +Set ExternalContactInfoId to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, ExternalContactInfoId will be stored as a varchar(100).) -Grant a queue right to this user. Takes a paramhash of which the elements -RightAppliesTo and RightName are important. =cut -sub GrantQueueRight { - - my $self = shift; - my %args = ( RightScope => 'Queue', - RightName => undef, - RightAppliesTo => undef, - PrincipalType => 'User', - PrincipalId => $self->Id, - @_); - - #ACL check handled in ACE.pm - - require RT::ACE; - -# $RT::Logger->debug("$self ->GrantQueueRight right:". $args{'RightName'} . -# " applies to queue ".$args{'RightAppliesTo'}."\n"); - - my $ace = new RT::ACE($self->CurrentUser); - - return ($ace->Create(%args)); -} -# }}} +=item ContactInfoSystem + +Returns the current value of ContactInfoSystem. +(In the database, ContactInfoSystem is stored as varchar(30).) + + -# {{{ GrantSystemRight +=item SetContactInfoSystem VALUE -=head2 GrantSystemRight -Grant a system right to this user. -The only element that's important to set is RightName. +Set ContactInfoSystem to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, ContactInfoSystem will be stored as a varchar(30).) + =cut -sub GrantSystemRight { - - my $self = shift; - my %args = ( RightScope => 'System', - RightName => undef, - RightAppliesTo => 0, - PrincipalType => 'User', - PrincipalId => $self->Id, - @_); - - - #ACL check handled in ACE.pm - - require RT::ACE; - my $ace = new RT::ACE($self->CurrentUser); - - return ($ace->Create(%args)); -} -# }}} +=item ExternalAuthId + +Returns the current value of ExternalAuthId. +(In the database, ExternalAuthId is stored as varchar(100).) -# {{{ sub HasQueueRight -=head2 HasQueueRight -Takes a paramhash which can contain -these items: - TicketObj => RT::Ticket or QueueObj => RT::Queue or Queue => integer - IsRequestor => undef, (for bootstrapping create) - Right => 'Right' +=item SetExternalAuthId VALUE -Returns 1 if this user has the right specified in the paramhash. for the queue -passed in. +Set ExternalAuthId to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, ExternalAuthId will be stored as a varchar(100).) -Returns undef if they don't =cut -sub HasQueueRight { - my $self = shift; - my %args = ( TicketObj => undef, - QueueObj => undef, - Queue => undef, - IsRequestor => undef, - Right => undef, - @_); - - my ($IsRequestor, $IsCc, $IsAdminCc, $IsOwner); - - if (defined $args{'Queue'}) { - $args{'QueueObj'} = new RT::Queue($self->CurrentUser); - $args{'QueueObj'}->Load($args{'Queue'}); - } - - if (defined $args{'TicketObj'}) { - $args{'QueueObj'} = $args{'TicketObj'}->QueueObj(); - } - - # {{{ Validate and load up the QueueId - unless ((defined $args{'QueueObj'}) and ($args{'QueueObj'}->Id)) { - require Carp; - $RT::Logger->debug(Carp::cluck ("$self->HasQueueRight Couldn't find a queue id")); - return undef; - } - - # }}} - - - # Figure out whether a user has the right we're asking about. - # first see if they have the right personally for the queue in question. - my $retval = $self->_HasRight(Scope => 'Queue', - AppliesTo => $args{'QueueObj'}->Id, - Right => $args{'Right'}, - IsOwner => $IsOwner); - - return ($retval) if (defined $retval); - - # then we see whether they have the right personally globally. - $retval = $self->HasSystemRight( $args{'Right'}); - - return ($retval) if (defined $retval); - - # now that we know they don't have the right personally, - - # {{{ Find out about whether the current user is a Requestor, Cc, AdminCc or Owner - - if (defined $args{'TicketObj'}) { - if ($args{'TicketObj'}->IsRequestor($self)) {#user is requestor - $IsRequestor = 1; - } - - if ($args{'TicketObj'}->IsCc($self)) { #If user is a cc - $IsCc = 1; - } - - if ($args{'TicketObj'}->IsAdminCc($self)) { #If user is an admin cc - $IsAdminCc = 1; - } - - if ($args{'TicketObj'}->IsOwner($self)) { #If user is an owner - $IsOwner = 1; - } - } - - if (defined $args{'QueueObj'}) { - if ($args{'QueueObj'}->IsCc($self)) { #If user is a cc - $IsCc = 1; - } - if ($args{'QueueObj'}->IsAdminCc($self)) { #If user is an admin cc - $IsAdminCc = 1; - } - - } - # }}} - - # then see whether they have the right for the queue as a member of a metagroup - - $retval = $self->_HasRight(Scope => 'Queue', - AppliesTo => $args{'QueueObj'}->Id, - Right => $args{'Right'}, - IsOwner => $IsOwner, - IsCc => $IsCc, - IsAdminCc => $IsAdminCc, - IsRequestor => $IsRequestor - ); - - return ($retval) if (defined $retval); - - # then we see whether they have the right globally as a member of a metagroup - $retval = $self->HasSystemRight( $args{'Right'}, - (IsOwner => $IsOwner, - IsCc => $IsCc, - IsAdminCc => $IsAdminCc, - IsRequestor => $IsRequestor - ) ); - - #If they haven't gotten it by now, they just lose. - return ($retval); - -} -# }}} - -# {{{ sub HasSystemRight +=item AuthSystem + +Returns the current value of AuthSystem. +(In the database, AuthSystem is stored as varchar(30).) + -=head2 HasSystemRight -takes an array of a single value and a paramhash. -The single argument is the right being passed in. -the param hash is some additional data. (IsCc, IsOwner, IsAdminCc and IsRequestor) +=item SetAuthSystem VALUE + + +Set AuthSystem to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, AuthSystem will be stored as a varchar(30).) -Returns 1 if this user has the listed 'right'. Returns undef if this user doesn't. =cut -sub HasSystemRight { - my $self = shift; - my $right = shift; - - my %args = ( IsOwner => undef, - IsCc => undef, - IsAdminCc => undef, - IsRequestor => undef, - @_); - - unless (defined $right) { - - $RT::Logger->debug("$self RT::User::HasSystemRight was passed in no right."); - return(undef); - } - return ( $self->_HasRight ( Scope => 'System', - AppliesTo => '0', - Right => $right, - IsOwner => $args{'IsOwner'}, - IsCc => $args{'IsCc'}, - IsAdminCc => $args{'IsAdminCc'}, - IsRequestor => $args{'IsRequestor'}, - - ) - ); - -} -# }}} +=item Gecos + +Returns the current value of Gecos. +(In the database, Gecos is stored as varchar(16).) + + -# {{{ sub _HasRight +=item SetGecos VALUE -=head2 sub _HasRight (Right => 'right', Scope => 'scope', AppliesTo => int, ExtendedPrincipals => SQL) -_HasRight is a private helper method for checking a user's rights. It takes -several options: +Set Gecos to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Gecos will be stored as a varchar(16).) + + +=cut + -=item Right is a textual right name +=item HomePhone -=item Scope is a textual scope name. (As of July these were Queue, Ticket and System +Returns the current value of HomePhone. +(In the database, HomePhone is stored as varchar(30).) -=item AppliesTo is the numerical Id of the object identified in the scope. For tickets, this is the queue #. for queues, this is the queue # -=item ExtendedPrincipals is an SQL select clause which assumes that the only -table in play is ACL. It's used by HasQueueRight to pass in which -metaprincipals apply. Actually, it's probably obsolete. TODO: remove it. -Returns 1 if a matching ACE was found. +=item SetHomePhone VALUE + + +Set HomePhone to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, HomePhone will be stored as a varchar(30).) -Returns undef if no ACE was found. =cut -sub _HasRight { - - my $self = shift; - my %args = ( Right => undef, - Scope => undef, - AppliesTo => undef, - IsRequestor => undef, - IsCc => undef, - IsAdminCc => undef, - IsOwner => undef, - ExtendedPrincipals => undef, - @_); - - if ($self->Disabled) { - $RT::Logger->debug ("Disabled User: ".$self->Name. - " failed access check for ".$args{'Right'}. - " to object ".$args{'Scope'}."/". - $args{'AppliesTo'}."\n"); - return (undef); - } - - if (!defined $args{'Right'}) { - $RT::Logger->debug("_HasRight called without a right\n"); - return(undef); - } - elsif (!defined $args{'Scope'}) { - $RT::Logger->debug("_HasRight called without a scope\n"); - return(undef); - } - elsif (!defined $args{'AppliesTo'}) { - $RT::Logger->debug("_HasRight called without an AppliesTo object\n"); - return(undef); - } - - #If we've cached a win or loss for this lookup say so - - #TODO Security +++ check to make sure this is complete and right - - #Construct a hashkey to cache decisions in - my ($hashkey); - { #it's ugly, but we need to turn off warning, cuz we're joining nulls. - local $^W=0; - $hashkey =$self->Id .":". join(':',%args); - } - - # $RT::Logger->debug($hashkey."\n"); - - #Anything older than 10 seconds needs to be rechecked - my $cache_timeout = (time - 10); - - - if ((defined $self->{'rights'}{"$hashkey"}) && - ($self->{'rights'}{"$hashkey"} == 1 ) && - (defined $self->{'rights'}{"$hashkey"}{'set'} ) && - ($self->{'rights'}{"$hashkey"}{'set'} > $cache_timeout)) { -# $RT::Logger->debug("Cached ACL win for ". -# $args{'Right'}.$args{'Scope'}. -# $args{'AppliesTo'}."\n"); - return ($self->{'rights'}{"$hashkey"}); - } - elsif ((defined $self->{'rights'}{"$hashkey"}) && - ($self->{'rights'}{"$hashkey"} == -1) && - (defined $self->{'rights'}{"$hashkey"}{'set'}) && - ($self->{'rights'}{"$hashkey"}{'set'} > $cache_timeout)) { - -# $RT::Logger->debug("Cached ACL loss decision for ". -# $args{'Right'}.$args{'Scope'}. -# $args{'AppliesTo'}."\n"); - - return(undef); - } - - - my $RightClause = "(RightName = '$args{'Right'}')"; - my $ScopeClause = "(RightScope = '$args{'Scope'}')"; - - #If an AppliesTo was passed in, we should pay attention to it. - #otherwise, none is needed - - $ScopeClause = "($ScopeClause AND (RightAppliesTo = $args{'AppliesTo'}))" - if ($args{'AppliesTo'}); - - - # The generic principals clause looks for users with my id - # and Rights that apply to _everyone_ - my $PrincipalsClause = "((PrincipalType = 'User') AND (PrincipalId = ".$self->Id."))"; - - - # If the user is the superuser, grant them the damn right ;) - my $SuperUserClause = - "(RightName = 'SuperUser') AND (RightScope = 'System') AND (RightAppliesTo = 0)"; - - # If we've been passed in an extended principals clause, we should lump it - # on to the existing principals clause. it'll make life easier - if ($args{'ExtendedPrincipals'}) { - $PrincipalsClause = "(($PrincipalsClause) OR ". - "($args{'ExtendedPrincipalsClause'}))"; - } - - my $GroupPrincipalsClause = "((ACL.PrincipalType = 'Group') ". - "AND (ACL.PrincipalId = Groups.Id) AND (GroupMembers.GroupId = Groups.Id) ". - " AND (GroupMembers.UserId = ".$self->Id."))"; - - - - - # {{{ A bunch of magic statements that make the metagroups listed - # work. basically, we if the user falls into the right group, - # we add the type of ACL check needed - my (@MetaPrincipalsSubClauses, $MetaPrincipalsClause); - - #The user is always part of the 'Everyone' Group - push (@MetaPrincipalsSubClauses, "((Groups.Name = 'Everyone') AND - (PrincipalType = 'Group') AND - (Groups.Id = PrincipalId))"); - - if ($args{'IsAdminCc'}) { - push (@MetaPrincipalsSubClauses, "((Groups.Name = 'AdminCc') AND - (PrincipalType = 'Group') AND - (Groups.Id = PrincipalId))"); - } - if ($args{'IsCc'}) { - push (@MetaPrincipalsSubClauses, " ((Groups.Name = 'Cc') AND - (PrincipalType = 'Group') AND - (Groups.Id = PrincipalId))"); - } - if ($args{'IsRequestor'}) { - push (@MetaPrincipalsSubClauses, " ((Groups.Name = 'Requestor') AND - (PrincipalType = 'Group') AND - (Groups.Id = PrincipalId))"); - } - if ($args{'IsOwner'}) { - - push (@MetaPrincipalsSubClauses, " ((Groups.Name = 'Owner') AND - (PrincipalType = 'Group') AND - (Groups.Id = PrincipalId))"); - } - - # }}} - - my ($GroupRightsQuery, $MetaGroupRightsQuery, $IndividualRightsQuery, $hitcount); - - # {{{ If there are any metaprincipals to be checked - if (@MetaPrincipalsSubClauses) { - #chop off the leading or - #TODO redo this with an array and a join - $MetaPrincipalsClause = join (" OR ", @MetaPrincipalsSubClauses); - - $MetaGroupRightsQuery = "SELECT COUNT(ACL.id) FROM ACL, Groups". - " WHERE " . - " ($ScopeClause) AND ($RightClause) AND ($MetaPrincipalsClause)"; - - # {{{ deal with checking if the user has a right as a member of a metagroup - -# $RT::Logger->debug("Now Trying $MetaGroupRightsQuery\n"); - $hitcount = $self->_Handle->FetchResult($MetaGroupRightsQuery); - - #if there's a match, the right is granted - if ($hitcount) { - $self->{'rights'}{"$hashkey"}{'set'} = time; - $self->{'rights'}{"$hashkey"} = 1; - return (1); - } - -# $RT::Logger->debug("No ACL matched MetaGroups query: $MetaGroupRightsQuery\n"); - - # }}} - - } - # }}} - - # {{{ deal with checking if the user has a right as a member of a group - # This query checks to se whether the user has the right as a member of a - # group - $GroupRightsQuery = "SELECT COUNT(ACL.id) FROM ACL, GroupMembers, Groups". - " WHERE " . - " (((($ScopeClause) AND ($RightClause)) OR ($SuperUserClause)) ". - " AND ($GroupPrincipalsClause))"; - - # $RT::Logger->debug("Now Trying $GroupRightsQuery\n"); - $hitcount = $self->_Handle->FetchResult($GroupRightsQuery); - - #if there's a match, the right is granted - if ($hitcount) { - $self->{'rights'}{"$hashkey"}{'set'} = time; - $self->{'rights'}{"$hashkey"} = 1; - return (1); - } - -# $RT::Logger->debug("No ACL matched $GroupRightsQuery\n"); - - # }}} - - # {{{ Check to see whether the user has a right as an individual - - # This query checks to see whether the current user has the right directly - $IndividualRightsQuery = "SELECT COUNT(ACL.id) FROM ACL WHERE ". - " ((($ScopeClause) AND ($RightClause)) OR ($SuperUserClause)) " . - " AND ($PrincipalsClause)"; - - - $hitcount = $self->_Handle->FetchResult($IndividualRightsQuery); - - if ($hitcount) { - $self->{'rights'}{"$hashkey"}{'set'} = time; - $self->{'rights'}{"$hashkey"} = 1; - return (1); - } - # }}} - - else { #If the user just doesn't have the right - -# $RT::Logger->debug("No ACL matched $IndividualRightsQuery\n"); - - #If nothing matched, return 0. - $self->{'rights'}{"$hashkey"}{'set'} = time; - $self->{'rights'}{"$hashkey"} = -1; - - - return (undef); - } -} +=item WorkPhone + +Returns the current value of WorkPhone. +(In the database, WorkPhone is stored as varchar(30).) + + -# }}} +=item SetWorkPhone VALUE -# {{{ sub CurrentUserCanModify -=head2 CurrentUserCanModify RIGHT +Set WorkPhone to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, WorkPhone will be stored as a varchar(30).) -If the user has rights for this object, either because -he has 'AdminUsers' or (if he\'s trying to edit himself and the right isn\'t an -admin right) 'ModifySelf', return 1. otherwise, return undef. =cut -sub CurrentUserCanModify { - my $self = shift; - my $right = shift; - - if ($self->CurrentUserHasRight('AdminUsers')) { - return (1); - } - #If the field is marked as an "administrators only" field, - # don\'t let the user touch it. - elsif ($self->_Accessible($right, 'admin')) { - return(undef); - } - - #If the current user is trying to modify themselves - elsif ( ($self->id == $self->CurrentUser->id) and - ($self->CurrentUserHasRight('ModifySelf'))) { - return(1); - } - - #If we don\'t have a good reason to grant them rights to modify - # by now, they lose - else { - return(undef); - } - -} -# }}} +=item MobilePhone + +Returns the current value of MobilePhone. +(In the database, MobilePhone is stored as varchar(30).) + -# {{{ sub CurrentUserHasRight -=head2 CurrentUserHasRight - - Takes a single argument. returns 1 if $Self->CurrentUser - has the requested right. returns undef otherwise +=item SetMobilePhone VALUE + + +Set MobilePhone to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, MobilePhone will be stored as a varchar(30).) + =cut -sub CurrentUserHasRight { - my $self = shift; - my $right = shift; - - return ($self->CurrentUser->HasSystemRight($right)); -} -# }}} +=item PagerPhone +Returns the current value of PagerPhone. +(In the database, PagerPhone is stored as varchar(30).) -# {{{ sub _Set -sub _Set { - my $self = shift; - - my %args = (Field => undef, - Value => undef, - @_ - ); - # Nobody is allowed to futz with RT_System or Nobody unless they - # want to change an email address. For 2.2, neither should have an email address +=item SetPagerPhone VALUE - if ($self->Privileged == 2) { - return (0, "Can not modify system users"); - } - unless ($self->CurrentUserCanModify($args{'Field'})) { - return (0, "Permission Denied"); - } +Set PagerPhone to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, PagerPhone will be stored as a varchar(30).) + + +=cut + + +=item Address1 + +Returns the current value of Address1. +(In the database, Address1 is stored as varchar(200).) - - #Set the new value - my ($ret, $msg)=$self->SUPER::_Set(Field => $args{'Field'}, - Value=> $args{'Value'}); - - return ($ret, $msg); -} -# }}} -# {{{ sub _Value +=item SetAddress1 VALUE -=head2 _Value -Takes the name of a table column. -Returns its value as a string, if the user passes an ACL check +Set Address1 to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Address1 will be stored as a varchar(200).) + =cut -sub _Value { - - my $self = shift; - my $field = shift; - - #If the current user doesn't have ACLs, don't let em at it. - - my @PublicFields = qw( Name EmailAddress Organization Disabled - RealName NickName Gecos ExternalAuthId - AuthSystem ExternalContactInfoId - ContactInfoSystem ); - - #if the field is public, return it. - if ($self->_Accessible($field, 'public')) { - return($self->SUPER::_Value($field)); - - } - #If the user wants to see their own values, let them - elsif ($self->CurrentUser->Id == $self->Id) { - return($self->SUPER::_Value($field)); - } - #If the user has the admin users right, return the field - elsif ($self->CurrentUserHasRight('AdminUsers')) { - return($self->SUPER::_Value($field)); - } - else { - return(undef); - } - -} +=item Address2 + +Returns the current value of Address2. +(In the database, Address2 is stored as varchar(200).) + + + +=item SetAddress2 VALUE + + +Set Address2 to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Address2 will be stored as a varchar(200).) + + +=cut + + +=item City + +Returns the current value of City. +(In the database, City is stored as varchar(100).) + + + +=item SetCity VALUE + + +Set City to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, City will be stored as a varchar(100).) + + +=cut + + +=item State + +Returns the current value of State. +(In the database, State is stored as varchar(100).) + + + +=item SetState VALUE + + +Set State to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, State will be stored as a varchar(100).) + + +=cut + + +=item Zip + +Returns the current value of Zip. +(In the database, Zip is stored as varchar(16).) + + + +=item SetZip VALUE + + +Set Zip to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Zip will be stored as a varchar(16).) + + +=cut + + +=item Country + +Returns the current value of Country. +(In the database, Country is stored as varchar(50).) + + + +=item SetCountry VALUE + + +Set Country to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Country will be stored as a varchar(50).) + + +=cut + + +=item Timezone + +Returns the current value of Timezone. +(In the database, Timezone is stored as varchar(50).) + + + +=item SetTimezone VALUE + + +Set Timezone to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, Timezone will be stored as a varchar(50).) + + +=cut + + +=item PGPKey + +Returns the current value of PGPKey. +(In the database, PGPKey is stored as text.) + + + +=item SetPGPKey VALUE + + +Set PGPKey to VALUE. +Returns (1, 'Status message') on success and (0, 'Error Message') on failure. +(In the database, PGPKey will be stored as a text.) + + +=cut + + +=item Creator + +Returns the current value of Creator. +(In the database, Creator is stored as int(11).) + + +=cut + + +=item Created + +Returns the current value of Created. +(In the database, Created is stored as datetime.) + + +=cut + + +=item LastUpdatedBy + +Returns the current value of LastUpdatedBy. +(In the database, LastUpdatedBy is stored as int(11).) + + +=cut + + +=item LastUpdated + +Returns the current value of LastUpdated. +(In the database, LastUpdated is stored as datetime.) + + +=cut + + + +sub _ClassAccessible { + { + + id => + {read => 1, type => 'int(11)', default => ''}, + Name => + {read => 1, write => 1, type => 'varchar(200)', default => ''}, + Password => + {read => 1, write => 1, type => 'varchar(40)', default => ''}, + Comments => + {read => 1, write => 1, type => 'blob', default => ''}, + Signature => + {read => 1, write => 1, type => 'blob', default => ''}, + EmailAddress => + {read => 1, write => 1, type => 'varchar(120)', default => ''}, + FreeformContactInfo => + {read => 1, write => 1, type => 'blob', default => ''}, + Organization => + {read => 1, write => 1, type => 'varchar(200)', default => ''}, + RealName => + {read => 1, write => 1, type => 'varchar(120)', default => ''}, + NickName => + {read => 1, write => 1, type => 'varchar(16)', default => ''}, + Lang => + {read => 1, write => 1, type => 'varchar(16)', default => ''}, + EmailEncoding => + {read => 1, write => 1, type => 'varchar(16)', default => ''}, + WebEncoding => + {read => 1, write => 1, type => 'varchar(16)', default => ''}, + ExternalContactInfoId => + {read => 1, write => 1, type => 'varchar(100)', default => ''}, + ContactInfoSystem => + {read => 1, write => 1, type => 'varchar(30)', default => ''}, + ExternalAuthId => + {read => 1, write => 1, type => 'varchar(100)', default => ''}, + AuthSystem => + {read => 1, write => 1, type => 'varchar(30)', default => ''}, + Gecos => + {read => 1, write => 1, type => 'varchar(16)', 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 => ''}, + Timezone => + {read => 1, write => 1, type => 'varchar(50)', default => ''}, + PGPKey => + {read => 1, write => 1, type => 'text', default => ''}, + Creator => + {read => 1, auto => 1, type => 'int(11)', default => '0'}, + Created => + {read => 1, auto => 1, type => 'datetime', default => ''}, + LastUpdatedBy => + {read => 1, auto => 1, type => 'int(11)', default => '0'}, + LastUpdated => + {read => 1, auto => 1, type => 'datetime', default => ''}, + + } +}; + + + eval "require RT::User_Overlay"; + if ($@ && $@ !~ qr{^Can't locate RT/User_Overlay.pm}) { + die $@; + }; + + eval "require RT::User_Vendor"; + if ($@ && $@ !~ qr{^Can't locate RT/User_Vendor.pm}) { + die $@; + }; + + eval "require RT::User_Local"; + if ($@ && $@ !~ qr{^Can't locate RT/User_Local.pm}) { + die $@; + }; + + + + +=head1 SEE ALSO + +This class allows "overlay" methods to be placed +into the following files _Overlay is for a System overlay by the original author, +_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations. + +These overlay files can contain new subs or subs to replace existing subs in this module. + +If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line + + no warnings qw(redefine); + +so that perl does not kick and scream when you redefine a subroutine or variable in your overlay. + +RT::User_Overlay, RT::User_Vendor, RT::User_Local + +=cut -# }}} -# }}} 1; - -- cgit v1.2.1 From d39d52aac8f38ea9115628039f0df5aa3ac826de Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 3 Dec 2004 20:40:48 +0000 Subject: import rt 3.2.2 --- rt/lib/RT/User.pm | 168 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 73 deletions(-) (limited to 'rt/lib/RT/User.pm') diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm index cbc10f5b4..10e7e84d5 100755 --- a/rt/lib/RT/User.pm +++ b/rt/lib/RT/User.pm @@ -1,8 +1,14 @@ -# BEGIN LICENSE BLOCK +# {{{ BEGIN BPS TAGGED BLOCK # -# Copyright (c) 1996-2003 Jesse Vincent +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# # -# (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 @@ -14,13 +20,29 @@ # 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 # Autogenerated by DBIx::SearchBuilder factory (by ) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -61,7 +83,7 @@ sub _Init { -=item Create PARAMHASH +=head2 Create PARAMHASH Create takes a hash of values and creates a row in the database: @@ -170,7 +192,7 @@ sub Create { -=item id +=head2 id Returns the current value of id. (In the database, id is stored as int(11).) @@ -179,14 +201,14 @@ Returns the current value of id. =cut -=item Name +=head2 Name Returns the current value of Name. (In the database, Name is stored as varchar(200).) -=item SetName VALUE +=head2 SetName VALUE Set Name to VALUE. @@ -197,14 +219,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Password +=head2 Password Returns the current value of Password. (In the database, Password is stored as varchar(40).) -=item SetPassword VALUE +=head2 SetPassword VALUE Set Password to VALUE. @@ -215,14 +237,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Comments +=head2 Comments Returns the current value of Comments. (In the database, Comments is stored as blob.) -=item SetComments VALUE +=head2 SetComments VALUE Set Comments to VALUE. @@ -233,14 +255,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Signature +=head2 Signature Returns the current value of Signature. (In the database, Signature is stored as blob.) -=item SetSignature VALUE +=head2 SetSignature VALUE Set Signature to VALUE. @@ -251,14 +273,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item EmailAddress +=head2 EmailAddress Returns the current value of EmailAddress. (In the database, EmailAddress is stored as varchar(120).) -=item SetEmailAddress VALUE +=head2 SetEmailAddress VALUE Set EmailAddress to VALUE. @@ -269,14 +291,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item FreeformContactInfo +=head2 FreeformContactInfo Returns the current value of FreeformContactInfo. (In the database, FreeformContactInfo is stored as blob.) -=item SetFreeformContactInfo VALUE +=head2 SetFreeformContactInfo VALUE Set FreeformContactInfo to VALUE. @@ -287,14 +309,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Organization +=head2 Organization Returns the current value of Organization. (In the database, Organization is stored as varchar(200).) -=item SetOrganization VALUE +=head2 SetOrganization VALUE Set Organization to VALUE. @@ -305,14 +327,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item RealName +=head2 RealName Returns the current value of RealName. (In the database, RealName is stored as varchar(120).) -=item SetRealName VALUE +=head2 SetRealName VALUE Set RealName to VALUE. @@ -323,14 +345,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item NickName +=head2 NickName Returns the current value of NickName. (In the database, NickName is stored as varchar(16).) -=item SetNickName VALUE +=head2 SetNickName VALUE Set NickName to VALUE. @@ -341,14 +363,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Lang +=head2 Lang Returns the current value of Lang. (In the database, Lang is stored as varchar(16).) -=item SetLang VALUE +=head2 SetLang VALUE Set Lang to VALUE. @@ -359,14 +381,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item EmailEncoding +=head2 EmailEncoding Returns the current value of EmailEncoding. (In the database, EmailEncoding is stored as varchar(16).) -=item SetEmailEncoding VALUE +=head2 SetEmailEncoding VALUE Set EmailEncoding to VALUE. @@ -377,14 +399,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item WebEncoding +=head2 WebEncoding Returns the current value of WebEncoding. (In the database, WebEncoding is stored as varchar(16).) -=item SetWebEncoding VALUE +=head2 SetWebEncoding VALUE Set WebEncoding to VALUE. @@ -395,14 +417,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item ExternalContactInfoId +=head2 ExternalContactInfoId Returns the current value of ExternalContactInfoId. (In the database, ExternalContactInfoId is stored as varchar(100).) -=item SetExternalContactInfoId VALUE +=head2 SetExternalContactInfoId VALUE Set ExternalContactInfoId to VALUE. @@ -413,14 +435,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item ContactInfoSystem +=head2 ContactInfoSystem Returns the current value of ContactInfoSystem. (In the database, ContactInfoSystem is stored as varchar(30).) -=item SetContactInfoSystem VALUE +=head2 SetContactInfoSystem VALUE Set ContactInfoSystem to VALUE. @@ -431,14 +453,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item ExternalAuthId +=head2 ExternalAuthId Returns the current value of ExternalAuthId. (In the database, ExternalAuthId is stored as varchar(100).) -=item SetExternalAuthId VALUE +=head2 SetExternalAuthId VALUE Set ExternalAuthId to VALUE. @@ -449,14 +471,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item AuthSystem +=head2 AuthSystem Returns the current value of AuthSystem. (In the database, AuthSystem is stored as varchar(30).) -=item SetAuthSystem VALUE +=head2 SetAuthSystem VALUE Set AuthSystem to VALUE. @@ -467,14 +489,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Gecos +=head2 Gecos Returns the current value of Gecos. (In the database, Gecos is stored as varchar(16).) -=item SetGecos VALUE +=head2 SetGecos VALUE Set Gecos to VALUE. @@ -485,14 +507,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item HomePhone +=head2 HomePhone Returns the current value of HomePhone. (In the database, HomePhone is stored as varchar(30).) -=item SetHomePhone VALUE +=head2 SetHomePhone VALUE Set HomePhone to VALUE. @@ -503,14 +525,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item WorkPhone +=head2 WorkPhone Returns the current value of WorkPhone. (In the database, WorkPhone is stored as varchar(30).) -=item SetWorkPhone VALUE +=head2 SetWorkPhone VALUE Set WorkPhone to VALUE. @@ -521,14 +543,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item MobilePhone +=head2 MobilePhone Returns the current value of MobilePhone. (In the database, MobilePhone is stored as varchar(30).) -=item SetMobilePhone VALUE +=head2 SetMobilePhone VALUE Set MobilePhone to VALUE. @@ -539,14 +561,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item PagerPhone +=head2 PagerPhone Returns the current value of PagerPhone. (In the database, PagerPhone is stored as varchar(30).) -=item SetPagerPhone VALUE +=head2 SetPagerPhone VALUE Set PagerPhone to VALUE. @@ -557,14 +579,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Address1 +=head2 Address1 Returns the current value of Address1. (In the database, Address1 is stored as varchar(200).) -=item SetAddress1 VALUE +=head2 SetAddress1 VALUE Set Address1 to VALUE. @@ -575,14 +597,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Address2 +=head2 Address2 Returns the current value of Address2. (In the database, Address2 is stored as varchar(200).) -=item SetAddress2 VALUE +=head2 SetAddress2 VALUE Set Address2 to VALUE. @@ -593,14 +615,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item City +=head2 City Returns the current value of City. (In the database, City is stored as varchar(100).) -=item SetCity VALUE +=head2 SetCity VALUE Set City to VALUE. @@ -611,14 +633,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item State +=head2 State Returns the current value of State. (In the database, State is stored as varchar(100).) -=item SetState VALUE +=head2 SetState VALUE Set State to VALUE. @@ -629,14 +651,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Zip +=head2 Zip Returns the current value of Zip. (In the database, Zip is stored as varchar(16).) -=item SetZip VALUE +=head2 SetZip VALUE Set Zip to VALUE. @@ -647,14 +669,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Country +=head2 Country Returns the current value of Country. (In the database, Country is stored as varchar(50).) -=item SetCountry VALUE +=head2 SetCountry VALUE Set Country to VALUE. @@ -665,14 +687,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Timezone +=head2 Timezone Returns the current value of Timezone. (In the database, Timezone is stored as varchar(50).) -=item SetTimezone VALUE +=head2 SetTimezone VALUE Set Timezone to VALUE. @@ -683,14 +705,14 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item PGPKey +=head2 PGPKey Returns the current value of PGPKey. (In the database, PGPKey is stored as text.) -=item SetPGPKey VALUE +=head2 SetPGPKey VALUE Set PGPKey to VALUE. @@ -701,7 +723,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=item Creator +=head2 Creator Returns the current value of Creator. (In the database, Creator is stored as int(11).) @@ -710,7 +732,7 @@ Returns the current value of Creator. =cut -=item Created +=head2 Created Returns the current value of Created. (In the database, Created is stored as datetime.) @@ -719,7 +741,7 @@ Returns the current value of Created. =cut -=item LastUpdatedBy +=head2 LastUpdatedBy Returns the current value of LastUpdatedBy. (In the database, LastUpdatedBy is stored as int(11).) @@ -728,7 +750,7 @@ Returns the current value of LastUpdatedBy. =cut -=item LastUpdated +=head2 LastUpdated Returns the current value of LastUpdated. (In the database, LastUpdated is stored as datetime.) @@ -738,7 +760,7 @@ Returns the current value of LastUpdated. -sub _ClassAccessible { +sub _CoreAccessible { { id => -- cgit v1.2.1 From d4d0590bef31071e8809ec046717444b95b3f30a Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 15 Oct 2005 09:11:20 +0000 Subject: import rt 3.4.4 --- rt/lib/RT/User.pm | 76 +++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'rt/lib/RT/User.pm') diff --git a/rt/lib/RT/User.pm b/rt/lib/RT/User.pm index 10e7e84d5..18edfd476 100755 --- a/rt/lib/RT/User.pm +++ b/rt/lib/RT/User.pm @@ -1,8 +1,8 @@ -# {{{ BEGIN BPS TAGGED BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC # # # (Except where explicitly superseded by other copyright notices) @@ -42,7 +42,7 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# }}} END BPS TAGGED BLOCK +# END BPS TAGGED BLOCK }}} # Autogenerated by DBIx::SearchBuilder factory (by ) # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST. # @@ -764,73 +764,73 @@ sub _CoreAccessible { { id => - {read => 1, type => 'int(11)', default => ''}, + {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''}, Name => - {read => 1, write => 1, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, Password => - {read => 1, write => 1, type => 'varchar(40)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 40, is_blob => 0, is_numeric => 0, type => 'varchar(40)', default => ''}, Comments => - {read => 1, write => 1, type => 'blob', default => ''}, + {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, Signature => - {read => 1, write => 1, type => 'blob', default => ''}, + {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, EmailAddress => - {read => 1, write => 1, type => 'varchar(120)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, FreeformContactInfo => - {read => 1, write => 1, type => 'blob', default => ''}, + {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'blob', default => ''}, Organization => - {read => 1, write => 1, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, RealName => - {read => 1, write => 1, type => 'varchar(120)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 120, is_blob => 0, is_numeric => 0, type => 'varchar(120)', default => ''}, NickName => - {read => 1, write => 1, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, Lang => - {read => 1, write => 1, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, EmailEncoding => - {read => 1, write => 1, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, WebEncoding => - {read => 1, write => 1, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, ExternalContactInfoId => - {read => 1, write => 1, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, ContactInfoSystem => - {read => 1, write => 1, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, ExternalAuthId => - {read => 1, write => 1, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, AuthSystem => - {read => 1, write => 1, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, Gecos => - {read => 1, write => 1, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, HomePhone => - {read => 1, write => 1, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, WorkPhone => - {read => 1, write => 1, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, MobilePhone => - {read => 1, write => 1, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, PagerPhone => - {read => 1, write => 1, type => 'varchar(30)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 30, is_blob => 0, is_numeric => 0, type => 'varchar(30)', default => ''}, Address1 => - {read => 1, write => 1, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, Address2 => - {read => 1, write => 1, type => 'varchar(200)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''}, City => - {read => 1, write => 1, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, State => - {read => 1, write => 1, type => 'varchar(100)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 100, is_blob => 0, is_numeric => 0, type => 'varchar(100)', default => ''}, Zip => - {read => 1, write => 1, type => 'varchar(16)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''}, Country => - {read => 1, write => 1, type => 'varchar(50)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 50, is_blob => 0, is_numeric => 0, type => 'varchar(50)', default => ''}, Timezone => - {read => 1, write => 1, type => 'varchar(50)', default => ''}, + {read => 1, write => 1, sql_type => 12, length => 50, is_blob => 0, is_numeric => 0, type => 'varchar(50)', default => ''}, PGPKey => - {read => 1, write => 1, type => 'text', default => ''}, + {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, Creator => - {read => 1, auto => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, Created => - {read => 1, auto => 1, type => 'datetime', default => ''}, + {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, LastUpdatedBy => - {read => 1, auto => 1, type => 'int(11)', default => '0'}, + {read => 1, auto => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, LastUpdated => - {read => 1, auto => 1, type => 'datetime', default => ''}, + {read => 1, auto => 1, sql_type => 11, length => 0, is_blob => 0, is_numeric => 0, type => 'datetime', default => ''}, } }; @@ -862,7 +862,7 @@ _Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customiz These overlay files can contain new subs or subs to replace existing subs in this module. -If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line +Each of these files should begin with the line no warnings qw(redefine); -- cgit v1.2.1