# ==================================================================
# Gossamer List - enhanced mailing list management system
#
#   Website  : http://gossamer-threads.com/
#   Support  : http://gossamer-threads.com/scripts/support/
#   CVS Info :                          
#   Revision : $Id: Authenticate.pm,v 1.15 2004/04/15 19:46:36 bao Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# Redistribution in part or in whole strictly prohibited.  Please
# see LICENSE file for full details.
# ==================================================================
#

package GList::Authenticate;
# ==================================================================

use strict;
use GList qw/:objects/;
use GT::Session::SQL;

sub auth {
# -------------------------------------------------------------------
# Runs the request auth function through the plugin system.
#
    ($_[0] eq 'GList::Authenticate') and shift;

    my ($auth, $args) = @_;
    my $code = exists $GList::Authenticate::{"auth_$auth"} ? $GList::Authenticate::{"auth_$auth"} : die "Invalid Authenticate method: auth_$auth called.";
    GT::Plugins->dispatch("$CFG->{priv_path}/lib/GList/Plugins", "auth_$auth", $code, $args);
}

sub auth_init {
# -------------------------------------------------------------------
# This function is guaranteed to be called before any other authentication
# function, but may be called multiple times during one request.
#
    return 1;
}

sub auth_get_user {
# -------------------------------------------------------------------
# This function returns user information for a given user, auto
# creating if it doesn't exist.
#
    my $args = shift;
    return $DB->table ('Users')->get({ usr_username => $args->{username}, usr_status => '1' });
}

sub auth_valid_user {
# -------------------------------------------------------------------
# This function returns 1 if the user/pass combo is valid, 0/undef
# otherwise.
#
    my $args = shift;
    my $user = $DB->table('Users')->get($args->{username});
    return if ( !$user );

    return ($user->{usr_password} eq GList::encrypt($args->{password}, $user->{usr_password})) ? 1 : 0;
}

sub auth_create_session {
# -------------------------------------------------------------------
# This function creates a session, and prints the header and returns a
# hash with session => $id, and redirect => 0/1.
#
    my $args = shift;

    my $uid        = $args->{username};
    my $use_cookie = ( $CFG->{user_session} ) ? 0 : 1;
    my $session = GT::Session::SQL->new ({
            _debug       => $CFG->{debug},
            tb           => $DB->table('Users_Sessions'),
            session_user_id => $uid,
            session_data => { cookie => $use_cookie, do => scalar($IN->param('do')) },
            expires      => $CFG->{session_exp},
        }
    );

    if ( $GT::Session::SQL::error ) {
        return { error => $GT::Session::SQL::error };
    }
# Delete all old sessions.
    $session->cleanup;
    if ($use_cookie) {
        print $IN->cookie(
            -name    => 'sid',
            -value   => $session->{info}->{session_id},
        )->cookie_header() . "\n";
    }
    return { session_id => $session->{info}->{session_id}, use_cookie => $use_cookie };
}

sub auth_valid_session {
# -------------------------------------------------------------------
# This functions checks to see if the session is valid, and returns the
# username.
    my $args = shift;
    my ($sid, $cookie);
    if ($IN->param ('sid')) {
        $sid = $IN->param ('sid');
    }
    elsif ( !$CFG->{user_session} and $IN->cookie ('sid') ) {
        $cookie = 1;
        $sid = $IN->cookie ('sid');
    }
    else { return }
    my $use_cookie = ( $CFG->{user_session} ) ? 0 : 1;

# Cookie authentication
    my $session = new GT::Session::SQL ({
        _debug       => $CFG->{debug},
        tb           => $DB->table('Users_Sessions'),
        session_id   => $sid,
        expires      => $CFG->{session_exp},
        session_data => { cookie => $use_cookie, do => scalar($IN->param('do')) },
    }) or return;

# Delete any of the user's expired sessions
    $sid = '' if ($session->{data}->{cookie});

# Must return the session id and the userid
    return { session_id => $session->{info}->{session_id}, use_cookie => $use_cookie, user_name => $session->{info}->{session_user_id} };
}

sub auth_delete_session {
# -------------------------------------------------------------------
# This function removes a session, returns 1 on success, undef on
# failure.
#
    my $args = shift;
    my $sid;
    if ( $IN->param('sid') ) {
        $sid = $IN->param ('sid');
    }
    elsif ( !$CFG->{user_session} and $IN->cookie('sid') ) {
        $sid = $IN->cookie ('sid');
    }
    else { return }

    my $session = new GT::Session::SQL (
        {
            _debug     => $CFG->{debug},
            tb         => $DB->table ('Users_Sessions'),
            session_id => $sid
        }
    ) or return;

# Delete the cookie
    $session->delete or return;

# Print the cookie header
    if (!$CFG->{user_session}) {
        print $IN->cookie(
            -name    => 'sid',
            -value   => $sid,
            -expires => '-1h'
        )->cookie_header() . "\n";
    }
    return 1;
}

sub auth_admin_valid_user {
#---------------------------------------------------------
#
    my $args = shift;

    my $admins = $CFG->{admin};
    foreach my $u (keys % $admins) {
        my $pass  = $admins->{$u}->[0];
        if ($u eq $args->{username} and GList::encrypt($args->{password}, $pass) eq $pass ) {
            return $args->{username};
        }
    }
    return;
}

sub auth_admin_create_session {
#---------------------------------------------------------
#
    my $args = shift;

# Clear out old sessions.
    require GT::Session::File;
    GT::Session::File->cleanup(1800, "$CFG->{priv_path}/tmp");

# Create a new session and save the information.
    my $session = new GT::Session::File ( directory => "$CFG->{priv_path}/tmp" );
    $session->{data}->{username} = $args->{username};
    my $session_id = $session->{id};
    $session->save;

# Now redirect to another URL and set cookies, or set URL string.
    my $redirect   = 0;
    my $use_cookie = ( $CFG->{user_session} ) ? 0 : 1;
    if ($use_cookie) {
        print $IN->cookie (
            -name       => 'session_id',
            -value      => $session_id,
            -path       => '/'
        )->cookie_header() . "\n";
    }
    return { session_id => $session_id, use_cookie => $use_cookie };
}

sub auth_admin_valid_session {
# -------------------------------------------------------------------
# This functions checks to see if the session is valid, and returns the
# username.
#
    my $args = shift;

# Clear out old sessions.
    require GT::Session::File;
    GT::Session::File->cleanup(1800, "$CFG->{priv_path}/tmp");

    my $session_id = $IN->param('session_id') || $IN->cookie('session_id') || return;
    my $session    = new GT::Session::File (
        directory => "$CFG->{priv_path}/tmp",
        id        => $session_id
    ) || return;

    my $use_cookie = ( $CFG->{user_session} ) ? 0 : 1;
    return { username => $session->{data}->{username}, session_id => $session_id, use_cookie => $use_cookie };
}

sub auth_admin_delete_session {
#--------------------------------------------------------
#
    require GT::Session::File;
    my $session_id = $IN->cookie('session_id') || $IN->param('session_id') || return;
    my $session    = new GT::Session::File(
        directory => "$CFG->{priv_path}/tmp",
        id        => $session_id
    ) || return;

    print $IN->cookie(
        -name   => 'session_id',
        -value  => '',
        -path   => '/'
    )->cookie_header() . "\n";

    return $session->delete();
}

1;
