#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
use RT::Principals;
use RT::ACE;
use RT::Interface::Email;
-use Encode;
use Text::Password::Pronounceable;
sub _OverlayAccessible {
AuthSystem => { public => 1, admin => 1 },
Gecos => { public => 1, admin => 1 },
PGPKey => { public => 1, admin => 1 },
- PrivateKey => { admin => 1 },
}
}
return ( 0, $self->loc("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, $self->loc('Name in use') ) if ( $TempUser->Id );
-
- my ($val, $message) = $self->ValidateEmailAddress( $args{'EmailAddress'} );
- return (0, $message) unless ( $val );
- } else {
- $RT::Logger->warning( "$self couldn't check for pre-existing users");
- }
-
+ my ( $val, $msg ) = $self->ValidateName( $args{'Name'} );
+ return ( 0, $msg ) unless $val;
+ ( $val, $msg ) = $self->ValidateEmailAddress( $args{'EmailAddress'} );
+ return ( 0, $msg ) unless ($val);
$RT::Handle->BeginTransaction();
# Groups deal with principal ids, rather than user ids.
return ( $id, $self->loc('User created') );
}
+=head2 ValidateName STRING
+
+Returns either (0, "failure reason") or 1 depending on whether the given
+name is valid.
+
+=cut
+
+sub ValidateName {
+ my $self = shift;
+ my $name = shift;
+
+ return ( 0, $self->loc('empty name') ) unless defined $name && length $name;
+
+ my $TempUser = RT::User->new( RT->SystemUser );
+ $TempUser->Load($name);
+
+ if ( $TempUser->id && ( !$self->id || $TempUser->id != $self->id ) ) {
+ return ( 0, $self->loc('Name in use') );
+ }
+ else {
+ return 1;
+ }
+}
+
=head2 ValidatePassword STRING
Returns either (0, "failure reason") or 1 depending on whether the given
}
}
+=head2 SetName
+
+Check to make sure someone else isn't using this name already
+
+=cut
+
+sub SetName {
+ my $self = shift;
+ my $Value = shift;
+
+ my ( $val, $message ) = $self->ValidateName($Value);
+ if ($val) {
+ return $self->_Set( Field => 'Name', Value => $Value );
+ }
+ else {
+ return ( 0, $message );
+ }
+}
+
=head2 SetEmailAddress
Check to make sure someone else isn't using this email address already
my $sha = Digest::SHA->new(512);
$sha->add($salt);
- $sha->add(encode_utf8($password));
+ $sha->add(Encode::encode( 'UTF-8', $password));
return join("!", "", "sha512", $salt, $sha->b64digest);
}
my $hash = MIME::Base64::decode_base64($stored);
# Decoding yields 30 byes; first 4 are the salt, the rest are substr(SHA256,0,26)
my $salt = substr($hash, 0, 4, "");
- return 0 unless substr(Digest::SHA::sha256($salt . Digest::MD5::md5($value)), 0, 26) eq $hash;
+ return 0 unless substr(Digest::SHA::sha256($salt . Digest::MD5::md5(Encode::encode( "UTF-8", $value))), 0, 26) eq $hash;
} elsif (length $stored == 32) {
# Hex nonsalted-md5
- return 0 unless Digest::MD5::md5_hex(encode_utf8($value)) eq $stored;
+ return 0 unless Digest::MD5::md5_hex(Encode::encode( "UTF-8", $value)) eq $stored;
} elsif (length $stored == 22) {
# Base64 nonsalted-md5
- return 0 unless Digest::MD5::md5_base64(encode_utf8($value)) eq $stored;
+ return 0 unless Digest::MD5::md5_base64(Encode::encode( "UTF-8", $value)) eq $stored;
} elsif (length $stored == 13) {
# crypt() output
- return 0 unless crypt(encode_utf8($value), $stored) eq $stored;
+ return 0 unless crypt(Encode::encode( "UTF-8", $value), $stored) eq $stored;
} else {
$RT::Logger->warning("Unknown password form");
return 0;
my $self = shift;
my $protect = shift;
- my $str = $self->AuthToken . $protect;
- utf8::encode($str);
+ my $str = Encode::encode( "UTF-8", $self->AuthToken . $protect );
return substr(Digest::MD5::md5_hex($str),0,16);
}
my $auth_string = shift;
my $protected = shift;
- my $str = $self->AuthToken . $protected;
- utf8::encode( $str );
+ my $str = Encode::encode( "UTF-8", $self->AuthToken . $protected );
return $auth_string eq substr(Digest::MD5::md5_hex($str),0,16);
}
my $name = _PrefName (shift);
my $default = shift;
- my $attr = RT::Attribute->new( $self->CurrentUser );
- $attr->LoadByNameAndObject( Object => $self, Name => $name );
-
- my $content = $attr->Id ? $attr->Content : undef;
+ my ($attr) = $self->Attributes->Named( $name );
+ my $content = $attr ? $attr->Content : undef;
unless ( ref $content eq 'HASH' ) {
return defined $content ? $content : $default;
}
return (0, $self->loc("No permission to set preferences"))
unless $self->CurrentUserCanModify('Preferences');
- my $attr = RT::Attribute->new( $self->CurrentUser );
- $attr->LoadByNameAndObject( Object => $self, Name => $name );
- if ( $attr->Id ) {
+ my ($attr) = $self->Attributes->Named( $name );
+ if ( $attr ) {
my ($ok, $msg) = $attr->SetContent( $value );
return (1, "No updates made")
if $msg eq "That is already the current value";
}
}
+=head2 DeletePreferences NAME/OBJ VALUE
+
+Delete user preferences associated with given object or name.
+
+=cut
+
+sub DeletePreferences {
+ my $self = shift;
+ my $name = _PrefName( shift );
+
+ return (0, $self->loc("No permission to set preferences"))
+ unless $self->CurrentUserCanModify('Preferences');
+
+ my ($attr) = $self->DeleteAttribute( $name );
+ return (0, $self->loc("Preferences were not found"))
+ unless $attr;
+
+ return 1;
+}
+
=head2 Stylesheet
Returns a list of valid stylesheets take from preferences.
sub WatchedQueues {
my $self = shift;
- my @roles = @_ || ('Cc', 'AdminCc');
+ my @roles = @_ ? @_ : ('Cc', 'AdminCc');
$RT::Logger->debug('WatcheQueues got user ' . $self->Name);
my $self = shift;
my $key = shift;
- unless ($self->CurrentUserCanModify('PrivateKey')) {
+ # Users should not be able to change their own PrivateKey values
+ unless ( $self->CurrentUser->HasRight(Right => 'AdminUsers', Object => $RT::System) ) {
return (0, $self->loc("Permission Denied"));
}