
#                                      Copyright 2024 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

package Whostmgr::360Monitoring::User;

use Moo;
use cPstrict;
extends 'Whostmgr::360Monitoring::Base';

use Cpanel::Imports;
use Cpanel::Plugins::RestApiClient        ();
use Whostmgr::360Monitoring::Validate     ();
use Cpanel::PwCache                       ();
use Cpanel::Transaction::File::JSON       ();
use Cpanel::Transaction::File::JSONReader ();

=head1 MODULE

C<Whostmgr::360Monitoring::User>

=head1 DESCRIPTION

C<Whostmgr::360Monitoring::User> is a class that provides methods to manage a 360Monitoring user and retrieve account information.

=head2 CONSTRUCTOR

=cut

sub BUILD {
    my ( $self, $args ) = @_;
    $self->_ensure_conf_dir();
    my $tx     = Cpanel::Transaction::File::JSONReader->new( path => $self->_conf_file );
    my $config = $tx->get_data();
    if ( $config && ref $config eq 'HASH' ) {
        $self->api_key( $config->{api_key} );
        $self->user_id( $config->{user_id} );
        $self->enabled( $config->{enabled} );
    }
}

=head1 ATTRIBUTES

=cut

has '_conf_dir' => (
    is   => 'rw',
    lazy => 1,
    isa  => sub {
        require Cpanel::Validate::FilesystemPath;
        Cpanel::Validate::FilesystemPath::validate_or_die( $_[0] );
    },
    builder => 1
);

has '_conf_file' => (
    is   => 'rw',
    lazy => 1,
    isa  => sub {
        require Cpanel::Validate::FilesystemPath;
        Cpanel::Validate::FilesystemPath::validate_or_die( $_[0] );
    },
    builder => 1
);

=head2 user_config - Hashref

Hashref containing the user configuration read from disk. This configuration is located at C<~/.360monitoring/config>

=cut

has 'user_config' => (
    is  => 'rw',
    isa => sub {
        die 'Not a Hashref.' if ref( $_[0] ) ne 'HASH';
    },
    builder => 1
);

=head2 api_key - string

The long-lived app token of the 360Monitoring account.
This is provided by the app360 backend upon user creation.

=cut

has 'api_key' => (
    is  => 'rw',
    isa => sub {
        !$_[0] || $_[0] =~ /^[0-9a-f]*$/ || die "Invalid api_key";
    },
    lazy    => 1,
    default => sub ($self) { $self->user_config->{api_key} // undef }
);

=head2 user_id - string

The 360Monitoring unique user ID.

=cut

has 'user_id' => (
    is  => 'rw',
    isa => sub {
        !$_[0] || $_[0] =~ /^[0-9a-f]*$/ || die "Invalid user_id";
    },
    lazy    => 1,
    default => sub ($self) { $self->user_config->{user_id} // '' }
);

=head2 enabled - boolean

Whether the 360Monitoring user is enabled.

=cut

has 'enabled' => (
    is  => 'rw',
    isa => sub {
        require Cpanel::Validate::Boolean;
        Cpanel::Validate::Boolean::validate_or_die( $_[0] );
    },
);

sub _build__conf_dir ($self) {
    my $home = Cpanel::PwCache::gethomedir( $self->username );
    die locale()->maketext( "No home directory found for [_1].", $self->username ) if !$home;
    return "$home/.360monitoring";
}

sub _build__conf_file ($self) {
    my $dir       = $self->_conf_dir;
    my $conf_file = "$dir/config";
    return $conf_file;
}

sub _build_user_config ($self) {
    $self->_ensure_conf_dir();
    my $tx     = Cpanel::Transaction::File::JSONReader->new( path => $self->_conf_file );
    my $config = $tx->get_data();
    return ( $config && ref $config eq 'HASH' ) ? $config : {};
}

sub _build_api ($self) {
    require Whostmgr::360Monitoring::ApiClient;
    my $api = Whostmgr::360Monitoring::ApiClient->new( username => $self->username );
    $api->auth_token( $self->session_token );
    $api->base_url( $self->cluster_endpoint );
    return $api;
}

=head1 METHODS

=head2 save_user_info( \%user_info )

Persist user configuration information on disk.

=head3 ARGUMENTS

A Hashref containing the requisite user information.
This is retreived from the 360Monitoring backend upon authentication, and shouldn't be manually supplied.

=head3 RETURNS

1 if saving to disk is successful, dies on failure.

=head3 EXAMPLES

From C<Whostmgr::360Monitoring::Auth::auth_session()>:

$self->api->method('POST');

$self->api->base_url( $user_info{cluster_endpoint} );

$self->api->endpoint( "auth/tokens/token/" . $user_info{master_user_id} );

$self->api->auth_token( $user_info{auth_token} );

$self->api->payload( { access_token => $user_info{auth_token} } );

$response = $self->api->run();

...

$user->save_user_info( $response->{data} );

=cut

sub save_user_info ($self) {
    my $info = {
        user_id => $self->user_id,
        api_key => $self->api_key,
        enabled => $self->enabled ? 1 : 0.
    };

    my $tx = Cpanel::Transaction::File::JSON->new(
        path        => $self->_conf_file,
        permissions => 0600,
        ownership   => [ $self->username ]
    );
    $tx->set_data($info);
    $tx->save_or_die();

    $self->user_config($info);
    return 1;
}

=head2 reset_config()

Resets the cPanel user's 360Monitoring config.

=head3 ARGUMENTS

=over

=item None.

=back

=head3 RETURNS

A new Whostmgr::360Monitoring::User object.

=head3 EXAMPLES

my $user = Whostmgr::360Monitoring::User->new( 'cpanel_username' => $user );

$user = $user->reset_config();

=cut

sub reset_config ($self) {
    require Cpanel::FileUtils::Move;

    my $dest = $self->_conf_file . "." . time;
    if ( Cpanel::FileUtils::Move::safemv( $self->_conf_file, $dest ) ) {
        return Whostmgr::360Monitoring::User->new( 'cpanel_username' => $self->cpanel_username );
    }

    die locale()->maketext('Failed to remove the current [asis,Server Monitoring] user.');
    return 0;
}

# File operations in a user's homedir shouldn't be run as the root user.
# Can fix this later or move the config to /var/cpanel or userdata.
sub _ensure_conf_dir ($self) {
    mkdir( $self->_conf_dir, 0755 );
    return 1;
}

1;
