mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
Fixed a bug in the main run loop whereby the objects array wasn't freed until shutdown, which sometimes meant objects got destroyed after the application, which is bad when the objects use the application to find services, etc. (This doesn't happen with services since services are not allowed to store references to the application, either directly or indirectly through references to objects or service instances.) Fixed the logout code to wait until the user tries to do something that requires login before clearing the logging out flag. This fixes a bug with HTTP whereby if a user logged out then his UA wouldn't ever be sent a 401 so wouldn't ever lose the authentication info, because browsers send the authentication info regardless of whether a page needs it or not. Also took the opportunity to remove a potential bug in the input validator code: store the admin message instead of a reference to the user object which might end up with a lifetime longer than expected.
This commit is contained in:
parent
0324923ec4
commit
09282c5818
@ -76,6 +76,12 @@ sub run {
|
||||
# reference to us and we wouldn't want a memory leak...
|
||||
$self->defaultOutput(undef);
|
||||
} while ($self->input->next());
|
||||
# clear the objects hash here, so that objects are removed before
|
||||
# us, otherwise they can't refer back to us during shutdown.
|
||||
# don't need to do the same to services as services should never
|
||||
# use the application object during shutdown. (They shouldn't be
|
||||
# able to. If they can, there is a circular reference.)
|
||||
$self->objects([]);
|
||||
$self->input(undef); # shutdown the input service instance
|
||||
$self->dump(5, 'PLIF application completed normally.');
|
||||
}
|
||||
|
@ -46,10 +46,25 @@ sub provides {
|
||||
$class->SUPER::provides($service));
|
||||
}
|
||||
|
||||
sub objectProvides {
|
||||
my $class = shift;
|
||||
my($service) = @_;
|
||||
return ($service eq 'user.login.deniedUserHandle' or $class->SUPER::objectProvides($service));
|
||||
}
|
||||
|
||||
sub objectInit {
|
||||
my $self = shift;
|
||||
my($app, $user) = @_;
|
||||
$self->SUPER::objectInit(@_);
|
||||
$self->user($user);
|
||||
}
|
||||
|
||||
# input.verify
|
||||
sub verifyInput {
|
||||
my $self = shift;
|
||||
my($app) = @_;
|
||||
# clear internal flags
|
||||
$self->userAdminMessage('');
|
||||
# let's see if there are any protocol-specific user authenticators
|
||||
my @result = $app->getSelectingServiceList('input.verify.user.'.$app->input->defaultOutputProtocol)->authenticateUser($app);
|
||||
if (not @result) {
|
||||
@ -59,14 +74,29 @@ sub verifyInput {
|
||||
# now let's see what that gave us
|
||||
if (@result) {
|
||||
# horrah, somebody knew what to do!
|
||||
if ((defined($result[0])) and ($result[0]->checkLogin())) {
|
||||
if (defined($result[0])) {
|
||||
my $canLogin = $result[0]->checkLogin();
|
||||
if ($canLogin) {
|
||||
if ($canLogin != 0) {
|
||||
# can log in and not logged out
|
||||
$app->addObject($result[0]); # they will have returned a user object
|
||||
} else {
|
||||
# hmm, so apparently user is not authentic
|
||||
$self->errorState(\@result);
|
||||
# logged out (0E0 is true but numerically equal to 0)
|
||||
# flag user internally so we know to log them out
|
||||
# if they try to do something that requires login
|
||||
# (note: we can't store a reference to an object
|
||||
# ourselves, so create an object to hold the
|
||||
# reference for us)
|
||||
$app->addObject($self->objectCreate($app, $result[0]));
|
||||
}
|
||||
} else {
|
||||
# hmm, so apparently user is not allowed to log in
|
||||
$self->dump(2, 'user '.($result[0]->userID).' tried logging in but their account is disabled');
|
||||
$self->userAdminMessage($result[0]->adminMessage);
|
||||
return $self; # supports user.login (reportInputVerificationError)
|
||||
}
|
||||
}
|
||||
}
|
||||
return; # nope, nothing to see here... (no error, anyway)
|
||||
}
|
||||
|
||||
@ -85,12 +115,7 @@ sub authenticateUser {
|
||||
sub reportInputVerificationError {
|
||||
my $self = shift;
|
||||
my($app) = @_;
|
||||
my $message = '';
|
||||
if (defined($self->errorState) and defined($self->errorState->[0])) {
|
||||
$message = $self->errorState->[0]->adminMessage;
|
||||
}
|
||||
$self->errorState(undef);
|
||||
$app->output->loginFailed(1, $message); # 1 means 'unknown username/password'
|
||||
$app->output->loginFailed(1, $self->userAdminMessage); # 1 means 'unknown username/password'
|
||||
}
|
||||
|
||||
# dispatcher.commands
|
||||
@ -109,6 +134,12 @@ sub cmdLoginLogout {
|
||||
if (defined($user)) {
|
||||
$user->logout();
|
||||
$app->removeObject($user);
|
||||
# flag user internally so we know to log them out
|
||||
# if they try to do something that requires login
|
||||
# (note: we can't store a reference to an object
|
||||
# ourselves, so create an object to hold the
|
||||
# reference for us)
|
||||
$self->addObject($self->objectCreate($app, $user));
|
||||
}
|
||||
$app->noCommand();
|
||||
}
|
||||
@ -162,13 +193,19 @@ sub hasRight {
|
||||
sub requireLogin {
|
||||
my $self = shift;
|
||||
my($app) = @_;
|
||||
my $deniedUser = $app->getObject('user.login.deniedUserHandle');
|
||||
if (defined($deniedUser)) {
|
||||
$deniedUser->user->loggedOut();
|
||||
$app->removeObject($deniedUser);
|
||||
} else {
|
||||
my $address = $app->input->address;
|
||||
if (defined($address) and not defined($app->getService('user.factory')->getUserByContactDetails($app, $app->input->protocol, $address))) {
|
||||
my($user, $password) = $self->createUser($app, $app->input->protocol, $address);
|
||||
$self->sendPassword($app, $user, $app->input->protocol, $password);
|
||||
} else {
|
||||
$app->output->loginFailed(0, '');
|
||||
return;
|
||||
}
|
||||
}
|
||||
$app->output->loginFailed(0, '');
|
||||
}
|
||||
|
||||
# dispatcher.output.generic
|
||||
|
@ -108,7 +108,6 @@ sub objectProvides {
|
||||
sub objectInit {
|
||||
my $self = shift;
|
||||
my($app, $userID, $mode, $password, $adminMessage, $newFieldID, $newFieldValue, $newFieldPassword, $fields, $groups, $rights) = @_;
|
||||
|
||||
$self->{'_DIRTY'} = {}; # make sure propertySet is happy
|
||||
$self->SUPER::objectInit(@_);
|
||||
$self->userID($userID);
|
||||
@ -295,15 +294,25 @@ sub logout {
|
||||
}
|
||||
}
|
||||
|
||||
sub loggedOut {
|
||||
my $self = shift;
|
||||
if ($self->mode == 1) {
|
||||
$self->mode(0); # clear flag
|
||||
}
|
||||
}
|
||||
|
||||
sub checkLogin {
|
||||
my $self = shift;
|
||||
# check to see if the account is disabled
|
||||
my $enabled = $self->mode == 0;
|
||||
# if user is logging out, clear flag
|
||||
if ($self->mode == 1) {
|
||||
$self->mode(0);
|
||||
# user is logging out
|
||||
return '0E0'; # true but zero
|
||||
} elsif ($self->mode == 0) {
|
||||
# account is in normal state
|
||||
return 1; # true
|
||||
} else {
|
||||
# account is disabled
|
||||
return 0; # false
|
||||
}
|
||||
return $enabled;
|
||||
}
|
||||
|
||||
sub joinGroup {
|
||||
|
Loading…
Reference in New Issue
Block a user