#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package Support::Command;

# This is the base class for all the Command subclasses in the 'Support' application.
#
# This app has a somewhat different approach to permissions and roles than other apps.
#

use lib '/app/tools/common/lib';

use lib '/app/tools/rps/lib';
use RPS::DB::Item::UserAccess;

use lib '/app/tools/support/lib';
use Support::Client::ClientList;
use Support::Module::ModuleList;

use base 'RSApache::Command::SessionedCommand';

use constant kAccessDeniedTemplate => '/app/tools/support/templates/access_denied.xsl';
use constant kMsgAccessDenied      => 'access_denied';

# Overload if the command should check write permissions
sub write_command { undef }

# Overload if the command has special Keyword access
sub access_keyword { undef }

sub execute {
    my ($self) = @_;

    my $response;

    # check session
    #
    $response = $self->_checkLogin();
    return $response if ($response);

    # Check if user has specific client access or if no restrictions apply
    $self->{client_filter} = []; # no entries means no restrictions
    my $userID = Common::RSApp::GetActiveUserID();
    my $userAccess = RPS::DB::Item::UserAccess->GetAll( "SELECT client_id FROM user_access WHERE user_id=$userID" );
    if ( $userAccess ) {
        while( $userAccess->hasNext() ) {
            my $ua = $userAccess->next();
            push @{$self->{client_filter}}, $ua->client_id if ( $ua->client_id && $ua->client_id != 0 );
        }
    }

    # !!! So, the command wants to seed the xml with some state.
    # !!! However, it isn't clear whether every subclass of this class
    # !!! will want the same state.  So, I'm going to make that process
    # !!! a method that we can override if necessary.
    #
    $self->_addToXML();

    # check permissions
    #

    # If the user doesn't have a RoyaltyShare Admin or RoyaltyShare Standard access level
    # then check if the user has been granted access to specific module(s).  If they
    # do have module access then continue permission checking.
    #
    unless ( $self->isRSUser() ) {
        unless ( $self->hasModuleAccess() ) {
            return $self->accessDeniedResponse();
        }
    }

    unless ( $self->canRead() ) {
        return $self->accessDeniedResponse();
    }

    if ( $self->write_command() && !$self->canWrite() ) {
        return $self->accessDeniedResponse();
    }

    # !!! Lets store our cookies
    Common::Preference::StoreCookies();

    # return nothing and let the derived Command execute
    #
    return undef;
}

sub canRead {
    my $self = shift;
    my $xml  = $self->{xml};

    my $module  = $xml->{Area} || $self->_area();
    my $command = $xml->{Cmd};
    my $keyword = $xml->{Keyword};

    Common::Log::Debug("Start: '$module' '$command'");
    return Support::Permission->CanRead( module => $module, page => $command, keyword => $keyword );
}

sub canWrite {
    my $self = shift;
    my $xml  = $self->{xml};

    my $module  = $xml->{Area} || $self->_area();
    my $command = $xml->{Cmd};
    my $keyword = $xml->{Keyword};

    return Support::Permission->CanWrite( module => $module, page => $command, keyword => $keyword );
}

# Check if the user has explicit module permissions defined.
# This will allow non-RS roles to access one or more modules.
sub hasModuleAccess {
    my $self    = shift;

    return (scalar $self->{client_filter} > 0) ? 1 : undef;
}

# return true if there are ANY access records for the current user that are for RoyaltyShare
sub isRSUser {
    my $self    = shift;
    my $user_id = Common::RSApp::GetActiveUserID();

    my $userAccess = RPS::DB::Item::UserAccess->LookupRoyaltyShareAccess($user_id);

    return $userAccess ? $userAccess->hasNext() : undef;
}

sub accessDeniedResponse {
    my ($self) = @_;
    $self->addMessageXML( type => "error", code => kMsgAccessDenied );
    return RSApache::Response::XSLT->new( $self->{xml}, kAccessDeniedTemplate );
}

sub _checkLogin {
    my ($self) = @_;
    my $session = RSApache::RSWebApp::GetSession();

    if ( !$session->IsValid() ) {
        return $self->invalidSessionResponse();
    }

    return undef;
}

sub _addToXML {
    my ($self) = @_;

    $self->{xml}{User}       = $self->_getUser();
    $self->{xml}{Navigation} = $self->_getNavigation();
    $self->{xml}{ClientSite} = $self->_getSite();
    $self->{xml}{Clients}    = $self->_getClients();
    $self->{xml}{Keyword}    = $self->_getKeyword();
}

sub _getSite {
    my $site = "https://" . $ENV{SERVER_NAME};
    $site =~ s/admin.//;

    return $site;
}

sub _getNavigation {
    my $self = shift;

    return Support::Module::ModuleList->new( restrictedList => 1 );
}

sub _getClients {
    my $self = shift;

    return Support::Client::ClientList->new( clientFilter => \@{$self->{client_filter}} );
}

sub _getKeyword {
    my $self = shift;

    return $self->access_keyword();
}

sub _area {
    my $self = shift;

    my ( $path, $args ) = split( '\?', $ENV{REQUEST_URI} );
    my @bits = split( '\/', $path );
    return $bits[2] || 'DEFAULT';
}

###
1;    # Play nicely.
###
