#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - autofixer2/fix_incomplete_user_deletes  Copyright 2022 cPanel, L.L.C.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

package autofixer2::fix_incomplete_user_deletes;

use strict;
use warnings;

use Cpanel::PwCache::Build           ();
use Cpanel::Validate::Username::Core ();
use Cpanel::AcctUtils::Domain        ();
use Whostmgr::Resellers::Check       ();
use Cpanel::iContact                 ();

BEGIN { unshift @INC, '/usr/local/cpanel'; }

exit run() unless caller;

sub run {

    return 0 unless supported_on_this_major( 82, 108 );

    my @invalid_users = find_invalid();

    # Short if nothing to do.
    return 0 if !@invalid_users;

    fix_invalid(@invalid_users);

    return 0;
}

sub find_invalid {
    my @invalid;

    Cpanel::PwCache::Build::init_passwdless_pwcache();
    my $pwcache_ref = Cpanel::PwCache::Build::fetch_pwcache();
    foreach my $pwref (@$pwcache_ref) {
        my $user = $pwref->[0];
        next unless -f "/var/cpanel/users/$user";

        next if Cpanel::Validate::Username::Core::reserved_username_check($user);
        next if length Cpanel::AcctUtils::Domain::getdomain($user);
        next if Whostmgr::Resellers::Check::is_reseller($user);
        push @invalid, $user;
    }
    return @invalid;
}

sub fix_invalid {
    my @invalid_users = sort @_;

    @invalid_users or die("Unexpectedly asked to fix invalid users but not passed a list");

    my $user_dir       = '/var/cpanel/users';
    my $user_cache_dir = "$user_dir.cache";
    my $invalid_dir    = "$user_dir.off";

    # Make the invalid dir.
    unlink $invalid_dir;         # In case it's a file.
    mkdir $invalid_dir, 0700;
    chmod 0700, $invalid_dir;    # Just in case it was there but wrong perms.
    -d $invalid_dir or die("Could not create $invalid_dir for invalid user backups");

    my $msg = "";
    foreach my $user (@invalid_users) {
        rename( "$user_dir/$user", "$invalid_dir/$user" );
        unlink "$user_cache_dir/$user";

        ### Disable unix account.
        $msg .= `/usr/sbin/usermod -L $user 2>&1`;
    }
    $msg .= `/scripts/updateuserdomains --force 2>&1`;

    $msg .= "\nWe recommend you consider also removing the unix account(s) and related files.\n";

    my $body = 'The following users have been identified as having not fully been removed from your system. ';
    $body .= "They are not resellers yet lack a primary domain. This makes them invalid users:\n\n";

    $body .= "    - $_\n" foreach @invalid_users;
    $body .= "\nThese user files have been moved to $invalid_dir and the UNIX accounts have been disabled.\n";

    $body .= $msg;

    Cpanel::iContact::icontact(
        subject => q{Invalid cPanel users detected on your system.},
        app     => "Application",                                      # Generic
        message => $body,
    );

}

# Do we run this code?
sub supported_on_this_major {
    my ( $min_ver, $max_ver ) = @_;

    my $major = get_major_version();

    return 0 if $major < $min_ver;
    return 0 if $major > $max_ver;

    return 1;
}

sub get_major_version {
    my $major_version;

    if ( open( my $fh, '<', '/usr/local/cpanel/version' ) ) {
        my $full_version = <$fh>;
        chomp $full_version;
        close($fh);
        ($major_version) = $full_version =~ /^[0-9]+\.([0-9]+)/;
    }

    # Safe default.
    return $major_version || 30;
}

1;
