#!/usr/bin/perl
#use Mooix::Thing;
use strict;
use warnings;
run sub {
	my $this=shift;
	%_=@_;
	my $username = $_{auth_username};
	length $username or $this->usage("bad auth_username");
	my $hostname = $_{auth_hostname};
	
	my $session;
	if (exists $_{session}) {
		$session=$_{session};
	}
	else {
		# Create a session. Note that all parameters are passed along,
		# and I pass @_ so it supports duplicate parameters, as
		# used by the scripted session.
		my $sessionparent = $_{sessionparent} or $this->usage("bad session parent");
		my $id = $this->sessions->newid(mkdir => 1, hint => $username);
		$session=$sessionparent->new(id => $id, owner => $this, @_);
	}
	
	if (! $this->allowlogin) {
		$session->write("The moo is not currently accepting logins. Try again later.");
		$this->sessions->remove(object => $session);
		exit 1;
	}
	
	# Go through the list of avatars (in reverse order, since
	# the guest is typically near the beginning), and ask 
	# each of the avatars in turn if the user can log in.
	foreach my $avatar (reverse $this->avatars->list) {
		next unless ref $avatar;
		# If a name was specified, the name of the avatar is checked
		# first.
		next if exists $_{name} &&
			lc($_{name} ne lc($avatar->name)) &&
			! grep { lc($_{name}) eq lc($_) } $avatar->alias;
		# As an optimization, so canlogin need not be run many
		# times on systems with a lot of users, check the username
		# against the avatar's users field.
		next if $avatar->defines('users') && !
		        grep { $_ eq $username } $avatar->users;
		# Some avatars (ie, guest) return a different avatar that
		# should be used.
		if ($avatar = $avatar->canlogin(username => $username, session => $session)) {
			unless ($_{quiet}) {
				unless ($_{nobanner}) {
					my $banner=$this->banner;
					if (length $banner) {
						$session->write($banner);
					}
				}
				$session->write("Logging in as ".$avatar->name.".");
			}

			my $lastlogid;
			unless ($_{nolog}) {
				# Add to lastlog.
				if (ref $this->lastlog) {
					$lastlogid = $this->lastlog->add(
							avatar => $avatar,
							name => $avatar->name,
							sessiontype => $session->parent,
							login => time(),
							hostname => $hostname,
							unixuser => $username,
							duration => '*',
					);
				}
			}

			# Finish setting up the session.
			$session->setup(avatar => $avatar, lastlogid => $lastlogid);
			
			# Tell the avatar to go ahead and handle the login.
			return unless $avatar->login(session => $session, hostname => $hostname, quiet => $_{quiet});
			return $session;
		}
	}
	
	$session->write("Access denied.");
	$this->sessions->remove(object => $session);
}
