616 lines
18 KiB
Perl
616 lines
18 KiB
Perl
package WebGUI::User;
|
|
|
|
=head1 LEGAL
|
|
|
|
-------------------------------------------------------------------
|
|
WebGUI is Copyright 2001-2006 Plain Black Corporation.
|
|
-------------------------------------------------------------------
|
|
Please read the legal notices (docs/legal.txt) and the license
|
|
(docs/license.txt) that came with this distribution before using
|
|
this software.
|
|
-------------------------------------------------------------------
|
|
http://www.plainblack.com info@plainblack.com
|
|
-------------------------------------------------------------------
|
|
|
|
=cut
|
|
|
|
use strict;
|
|
use WebGUI::Cache;
|
|
use WebGUI::Group;
|
|
use WebGUI::DatabaseLink;
|
|
use WebGUI::Utility;
|
|
|
|
=head1 NAME
|
|
|
|
Package WebGUI::User
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This package provides an object-oriented way of managing WebGUI users as well as getting/setting a users's profile data.
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use WebGUI::User;
|
|
$u = WebGUI::User->new($session,3); or $u = WebGUI::User->new($session,"new"); or $u = WebGUI::User->newByEmail($session, $email);
|
|
|
|
$authMethod = $u->authMethod("WebGUI");
|
|
$dateCreated = $u->dateCreated;
|
|
$karma = $u->karma;
|
|
$lastUpdated = $u->lastUpdated;
|
|
$languagePreference = $u->profileField("language",1);
|
|
$referringAffiliate = $u->referringAffiliate;
|
|
$status = $u->status("somestatus");
|
|
$username = $u->username("jonboy");
|
|
$arrayRef = $u->getGroups;
|
|
$member = $u->isInGroup($groupId);
|
|
|
|
$u->addToGroups(\@arr);
|
|
$u->deleteFromGroups(\@arr);
|
|
$u->delete;
|
|
|
|
WebGUI::User->validUserId($session, $userId);
|
|
|
|
=head1 METHODS
|
|
|
|
These methods are available from this class:
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------
|
|
sub _create {
|
|
my $session = shift;
|
|
my $userId = shift || $session->id->generate();
|
|
$session->db->write("insert into users (userId,dateCreated) values (?,?)",[$userId, time()]);
|
|
WebGUI::Group->new($session,2)->addUsers([$userId]);
|
|
WebGUI::Group->new($session,7)->addUsers([$userId]);
|
|
return $userId;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 addToGroups ( groups [, expireOffset ] )
|
|
|
|
Adds this user to the specified groups.
|
|
|
|
=head3 groups
|
|
|
|
An array reference containing a list of groups.
|
|
|
|
=head3 expireOffset
|
|
|
|
An override for the default offset of the grouping. Specified in seconds.
|
|
|
|
=cut
|
|
|
|
sub addToGroups {
|
|
my $self = shift;
|
|
my $groups = shift;
|
|
my $expireOffset = shift;
|
|
$self->uncache;
|
|
foreach my $groupId (@{$groups}) {
|
|
WebGUI::Group->new($self->session,$groupId)->addUsers([$self->userId],$expireOffset);
|
|
}
|
|
$self->session->stow->delete("gotGroupsForUser");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 authMethod ( [ value ] )
|
|
|
|
Returns the authentication method for this user.
|
|
|
|
=head3 value
|
|
|
|
If specified, the authMethod is set to this value. The only valid values are "WebGUI" and "LDAP". When a new account is created, authMethod is defaulted to "WebGUI".
|
|
|
|
=cut
|
|
|
|
sub authMethod {
|
|
my ($self, $value);
|
|
$self = shift;
|
|
$value = shift;
|
|
if (defined $value) {
|
|
$self->uncache;
|
|
$self->{_user}{"authMethod"} = $value;
|
|
$self->{_user}{"lastUpdated"} =$self->session->datetime->time();
|
|
$self->session->db->write("update users set authMethod=".$self->session->db->quote($value).",
|
|
lastUpdated=".$self->session->datetime->time()." where userId=".$self->session->db->quote($self->{_userId}));
|
|
}
|
|
return $self->{_user}{"authMethod"};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 canUseAdminMode ( )
|
|
|
|
Returns a boolean indicating whether the user has the basic privileges needed to turn on admin mode and use basic admin functions. Note this isn't checking for any special privileges like whether the user can create new users, etc.
|
|
|
|
=cut
|
|
|
|
sub canUseAdminMode {
|
|
my $self = shift;
|
|
my $pass = 1;
|
|
my $subnets = $self->session->config->get("adminModeSubnets") || [];
|
|
if (scalar(@$subnets)) {
|
|
$pass = WebGUI::Utility::isInSubnet($self->session->env->getIp, $subnets);
|
|
}
|
|
return $pass && $self->session->user->isInGroup(12)
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 dateCreated ( )
|
|
|
|
Returns the epoch for when this user was created.
|
|
|
|
=cut
|
|
|
|
sub dateCreated {
|
|
return $_[0]->{_user}{dateCreated};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 delete ( )
|
|
|
|
Deletes this user.
|
|
|
|
=cut
|
|
|
|
sub delete {
|
|
my $self = shift;
|
|
$self->uncache;
|
|
foreach my $groupId (@{$self->getGroups($self->userId)}) {
|
|
WebGUI::Group->new($self->session,$groupId)->deleteUsers([$self->userId]);
|
|
}
|
|
$self->session->db->write("delete from inbox where userId=? and (groupId is null or groupId='')",[$self->{_userId}]);
|
|
require WebGUI::Operation::Auth;
|
|
my $authMethod = WebGUI::Operation::Auth::getInstance($self->session,$self->authMethod,$self->{_userId});
|
|
$authMethod->deleteParams($self->{_userId});
|
|
my $rs = $self->session->db->read("select sessionId from userSession where userId=?",[$self->{_userId}]);
|
|
while (my ($id) = $rs->array) {
|
|
$self->session->db->write("delete from userSessionScratch where sessionId=?",[$id]);
|
|
}
|
|
$self->session->db->write("delete from userSession where userId=?",[$self->{_userId}]);
|
|
$self->session->db->write("delete from userProfileData where userId=?",[$self->{_userId}]);
|
|
$self->session->db->write("delete from users where userId=?",[$self->{_userId}]);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 deleteFromGroups ( groups )
|
|
|
|
Deletes this user from the specified groups.
|
|
|
|
=head3 groups
|
|
|
|
An array reference containing a list of groups.
|
|
|
|
=cut
|
|
|
|
sub deleteFromGroups {
|
|
my $self = shift;
|
|
my $groups = shift;
|
|
$self->uncache;
|
|
foreach my $groupId (@{$groups}) {
|
|
WebGUI::Group->new($self->session,$groupId)->deleteUsers([$self->userId]);
|
|
}
|
|
$self->session->stow->delete("gotGroupsForUser");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 DESTROY ( )
|
|
|
|
Deconstructor.
|
|
|
|
=cut
|
|
|
|
sub DESTROY {
|
|
my $self = shift;
|
|
undef $self;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getGroups ( [ withoutExpired ] )
|
|
|
|
Returns an array reference containing a list of groups this user is in.
|
|
|
|
=head3 withoutExpired
|
|
|
|
If set to "1" then the listing will not include expired groupings. Defaults to "0".
|
|
|
|
=cut
|
|
|
|
sub getGroups {
|
|
my $self = shift;
|
|
my $withoutExpired = shift;
|
|
my $clause = "";
|
|
if ($withoutExpired) {
|
|
$clause = "and expireDate>".$self->session->datetime->time();
|
|
}
|
|
my $gotGroupsForUser = $self->session->stow->get("gotGroupsForUser");
|
|
if (exists $gotGroupsForUser->{$self->userId}) {
|
|
return $gotGroupsForUser->{$self->userId};
|
|
} else {
|
|
my @groups = $self->session->db->buildArray("select groupId from groupings where userId=? $clause", [$self->userId]);
|
|
my $isInGroup = $self->session->stow->get("isInGroup");
|
|
foreach my $gid (@groups) {
|
|
$isInGroup->{$self->userId}{$gid} = 1;
|
|
}
|
|
$self->session->stow->set("isInGroup",$isInGroup);
|
|
$gotGroupsForUser->{$self->userId} = \@groups;
|
|
$self->session->stow->set("gotGroupsForUser",$gotGroupsForUser);
|
|
return \@groups;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
# This method is depricated and is provided only for reverse compatibility. See WebGUI::Auth instead.
|
|
sub identifier {
|
|
my ($self, $value);
|
|
$self = shift;
|
|
$value = shift;
|
|
if (defined $value) {
|
|
$self->uncache;
|
|
$self->{_user}{"identifier"} = $value;
|
|
$self->session->db->write("update authentication set fieldData=".$self->session->db->quote($value)."
|
|
where userId=".$self->session->db->quote($self->{_userId})." and authMethod='WebGUI' and fieldName='identifier'");
|
|
}
|
|
return $self->{_user}{"identifier"};
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 isInGroup ( [ groupId ] )
|
|
|
|
Returns a boolean (0|1) value signifying that the user has the required privileges. Always returns true for Admins.
|
|
|
|
=head3 groupId
|
|
|
|
The group that you wish to verify against the user. Defaults to group with Id 3 (the Admin group).
|
|
|
|
=cut
|
|
|
|
sub isInGroup {
|
|
my (@data, $groupId);
|
|
my ($self, $gid, $secondRun) = @_;
|
|
$gid = 3 unless (defined $gid);
|
|
my $uid = $self->userId;
|
|
### The following several checks are to increase performance. If this section were removed, everything would continue to work as normal.
|
|
#my $eh = $self->session->errorHandler;
|
|
#$eh->warn("Group Id is: $gid for ".$tgroup->name);
|
|
return 1 if ($gid eq '7'); # everyone is in the everyone group
|
|
return 1 if ($gid eq '1' && $uid eq '1'); # visitors are in the visitors group
|
|
return 1 if ($gid eq '2' && $uid ne '1'); # if you're not a visitor, then you're a registered user
|
|
### Get data for auxillary checks.
|
|
my $isInGroup = $self->session->stow->get("isInGroup");
|
|
### Look to see if we've already looked up this group.
|
|
return $isInGroup->{$uid}{$gid} if exists $isInGroup->{$uid}{$gid};
|
|
### Lookup the actual groupings.
|
|
my $group = WebGUI::Group->new($self->session,$gid);
|
|
### Check for groups of groups.
|
|
my $users = $group->getAllUsers();
|
|
foreach my $user (@{$users}) {
|
|
$isInGroup->{$user}{$gid} = 1;
|
|
if ($uid eq $user) {
|
|
$self->session->stow->set("isInGroup",$isInGroup);
|
|
return 1;
|
|
}
|
|
}
|
|
$isInGroup->{$uid}{$gid} = 0;
|
|
$self->session->stow->set("isInGroup",$isInGroup);
|
|
return 0;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 karma ( [ amount, source, description ] )
|
|
|
|
Returns the current level of karma this user has earned.
|
|
|
|
=head3 amount
|
|
|
|
An integer to modify this user's karma by. Note that this number can be positive or negative.
|
|
|
|
=head3 source
|
|
|
|
A descriptive source for this karma. Typically it would be something like "MessageBoard (49)" or "Admin (3)". Source is used to track where a karma modification came from.
|
|
|
|
=head3 description
|
|
|
|
A description of why this user's karma was modified. For instance it could be "Message Board Post" or "He was a good boy!".
|
|
|
|
=cut
|
|
|
|
sub karma {
|
|
my $self = shift;
|
|
my $amount = shift;
|
|
my $source = shift;
|
|
my $description = shift;
|
|
if (defined $amount && defined $source && defined $description) {
|
|
$self->uncache;
|
|
$self->{_user}{karma} += $amount;
|
|
$self->session->db->write("update users set karma=karma+? where userId=?", [$amount, $self->userId]);
|
|
$self->session->db->write("insert into karmaLog values (?,?,?,?,?)",[$self->userId, $amount, $source, $description, $self->session->datetime->time()]);
|
|
}
|
|
return $self->{_user}{karma};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 lastUpdated ( )
|
|
|
|
Returns the epoch for when this user was last modified.
|
|
|
|
=cut
|
|
|
|
sub lastUpdated {
|
|
return $_[0]->{_user}{lastUpdated};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 new ( session, userId [, overrideId ] )
|
|
|
|
Constructor.
|
|
|
|
=head3 session
|
|
|
|
The session variable.
|
|
|
|
=head3 userId
|
|
|
|
The userId of the user you're creating an object reference for. If left blank it will default to "1" (Visitor). If specified as "new" then a new user account will be created and assigned the next available userId.
|
|
|
|
=head3 overrideId
|
|
|
|
A unique ID to use instead of the ID that WebGUI will generate for you. It must be absolutely unique and can be up to 22 alpha numeric characters long.
|
|
|
|
=cut
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
my $userId = shift || 1;
|
|
my $overrideId = shift;
|
|
$userId = _create($session, $overrideId) if ($userId eq "new");
|
|
my $cache = WebGUI::Cache->new($session,["user",$userId]);
|
|
my $userData = $cache->get;
|
|
unless ($userData->{_userId} && $userData->{_user}{username}) {
|
|
my %user;
|
|
tie %user, 'Tie::CPHash';
|
|
%user = $session->db->quickHash("select * from users where userId=".$session->db->quote($userId));
|
|
my %profile = $session->db->buildHash("select userProfileField.fieldName, userProfileData.fieldData
|
|
from userProfileField, userProfileData where userProfileField.fieldName=userProfileData.fieldName and
|
|
userProfileData.userId=".$session->db->quote($user{userId}));
|
|
my %default = $session->db->buildHash("select fieldName, dataDefault from userProfileField");
|
|
foreach my $key (keys %default) {
|
|
my $value;
|
|
if ($profile{$key} eq "" && $default{$key}) {
|
|
$value = eval($default{$key});
|
|
if (ref $value eq "ARRAY") {
|
|
$profile{$key} = $$value[0];
|
|
} else {
|
|
$profile{$key} = $value;
|
|
}
|
|
}
|
|
}
|
|
$profile{alias} = $user{username} if ($profile{alias} =~ /^\W+$/ || $profile{alias} eq "");
|
|
$userData = {
|
|
_userId => $userId,
|
|
_user => \%user,
|
|
_profile => \%profile
|
|
};
|
|
$cache->set($userData, 60*60*24);
|
|
}
|
|
$userData->{_session} = $session;
|
|
bless $userData, $class;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 newByEmail ( session, email )
|
|
|
|
Instanciates a user by email address. Returns undef if the email address could not be found.
|
|
|
|
=head3 session
|
|
|
|
A reference to the current session.
|
|
|
|
=head3 email
|
|
|
|
The email address to search for.
|
|
|
|
=cut
|
|
|
|
sub newByEmail {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
my $email = shift;
|
|
my ($id) = $session->dbSlave->quickArray("select userId from userProfileData where fieldName='email' and fieldData=?",[$email]);
|
|
my $user = $class->new($session, $id);
|
|
return undef if ($user->userId eq "1"); # visitor is never valid for this method
|
|
return undef unless $user->username;
|
|
return $user;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 profileField ( fieldName [, value ] )
|
|
|
|
Returns a profile field's value. If "value" is specified, it also sets the field to that value.
|
|
|
|
=head3 fieldName
|
|
|
|
The profile field name such as "language" or "email" or "cellPhone".
|
|
|
|
=head3 value
|
|
|
|
The value to set the profile field name to.
|
|
|
|
=cut
|
|
|
|
sub profileField {
|
|
my ($self, $fieldName, $value);
|
|
$self = shift;
|
|
$fieldName = shift;
|
|
$value = shift;
|
|
if (!exists $self->{_profile}{$fieldName} && !$self->session->db->quickArray("SELECT COUNT(*) FROM userProfileField WHERE fieldName = ?", [$fieldName])) {
|
|
$self->session->errorHandler->warn("No such profile field: $fieldName");
|
|
return undef;
|
|
}
|
|
if (defined $value) {
|
|
$self->uncache;
|
|
$self->{_profile}{$fieldName} = $value;
|
|
$self->session->db->write("delete from userProfileData where userId=? and fieldName=?",[$self->{_userId}, $fieldName]);
|
|
$self->session->db->write("insert into userProfileData values (?,?,?)", [$self->{_userId}, $fieldName,$value]);
|
|
my $time = $self->session->datetime->time();
|
|
$self->{_user}{"lastUpdated"} = $time;
|
|
$self->session->db->write("update users set lastUpdated=? where userId=?", [$time, $self->{_userId}]);
|
|
}
|
|
return $self->{_profile}{$fieldName};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 referringAffiliate ( [ value ] )
|
|
|
|
Returns the unique identifier of the affiliate that referred this user to the site.
|
|
|
|
=head3 value
|
|
|
|
An integer containing the unique identifier of the affiliate.
|
|
|
|
=cut
|
|
|
|
sub referringAffiliate {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
if (defined $value) {
|
|
$self->uncache;
|
|
$self->{_user}{"referringAffiliate"} = $value;
|
|
$self->{_user}{"lastUpdated"} =$self->session->datetime->time();
|
|
$self->session->db->write("update users set referringAffiliate=".$self->session->db->quote($value).",
|
|
lastUpdated=".$self->session->datetime->time()." where userId=".$self->session->db->quote($self->userId));
|
|
}
|
|
return $self->{_user}{"referringAffiliate"};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 session ( )
|
|
|
|
Returns a reference to the current session.
|
|
|
|
=cut
|
|
|
|
sub session {
|
|
my $self = shift;
|
|
return $self->{_session};
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 status ( [ value ] )
|
|
|
|
Returns the status of the user.
|
|
|
|
=head3 value
|
|
|
|
If specified, the status is set to this value. Possible values are 'Active', 'Selfdestructed' and 'Deactivated'.
|
|
|
|
=cut
|
|
|
|
sub status {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
if (defined $value) {
|
|
$self->uncache;
|
|
$self->{_user}{"status"} = $value;
|
|
$self->{_user}{"lastUpdated"} =$self->session->datetime->time();
|
|
$self->session->db->write("update users set status=".$self->session->db->quote($value).",
|
|
lastUpdated=".$self->session->datetime->time()." where userId=".$self->session->db->quote($self->userId));
|
|
if ($value eq 'Deactivated') {
|
|
my $rs = $self->session->db->read("select sessionId from userSession where userId=?",[$self->{_userId}]);
|
|
while (my ($id) = $rs->array) {
|
|
$self->session->db->write("delete from userSessionScratch where sessionId=?",[$id]);
|
|
}
|
|
$self->session->db->write("delete from userSession where userId=?",[$self->{_userId}]);
|
|
}
|
|
}
|
|
return $self->{_user}{"status"};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 uncache ( )
|
|
|
|
Deletes this user object out of the cache.
|
|
|
|
=cut
|
|
|
|
sub uncache {
|
|
my $self = shift;
|
|
my $cache = WebGUI::Cache->new($self->session,["user",$self->userId]);
|
|
$cache->delete;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 username ( [ value ] )
|
|
|
|
Returns the username.
|
|
|
|
=head3 value
|
|
|
|
If specified, the username is set to this value.
|
|
|
|
=cut
|
|
|
|
sub username {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
if (defined $value) {
|
|
$self->uncache;
|
|
$self->{_user}{"username"} = $value;
|
|
$self->{_user}{"lastUpdated"} = $self->session->datetime->time();
|
|
$self->session->db->write("update users set username=".$self->session->db->quote($value).",
|
|
lastUpdated=".$self->session->datetime->time()." where userId=".$self->session->db->quote($self->userId));
|
|
}
|
|
return $self->{_user}{"username"};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 userId ( )
|
|
|
|
Returns the userId for this user.
|
|
|
|
=cut
|
|
|
|
sub userId {
|
|
return $_[0]->{_userId};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 validUserId ( userId )
|
|
|
|
Returns true if the userId exists in the users table.
|
|
|
|
=cut
|
|
|
|
sub validUserId {
|
|
my ($class, $session, $userId) = @_;
|
|
my $sth = $session->db->read('select userId from users where userId='.$session->db->quote($userId));
|
|
return ($sth->rows == 1);
|
|
}
|
|
|
|
1;
|