\!/ KyuuKazami \!/

Path : /scripts/
Upload :
Current File : //scripts/modify_accounts

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

package scripts::modify_accounts;

use strict;
use warnings;

use Cpanel::AcctUtils::Owner             ();
use Cpanel::AccessIds::ReducedPrivileges ();
use Cpanel::Config                       ();
use Cpanel::Logger                       ();
use Cpanel::PwCache                      ();
use Cpanel::Reseller                     ();
use Cpanel::Services::Cpsrvd             ();
use Cpanel::Themes::Utils                ();
use Cpanel::Config::CpUserGuard          ();
use Whostmgr::ACLS                       ();

use File::Path   ();
use Getopt::Long ();

my $logger = Cpanel::Logger->new();

local $| = 1;

exit main(@ARGV) unless caller;

sub main {
    my @args = @_;

    if ( $> != 0 ) {
        $logger->die("Sorry, only root can use this script.");
    }

    my ( $theme, $users, $help, $all_users, $reseller, $style );

    Getopt::Long::GetOptionsFromArray(
        \@args,
        'help'                      => \$help,
        'theme=s'                   => \$theme,
        'all-users'                 => \$all_users,
        'users=s'                   => \$users,
        'all-users-from-reseller=s' => \$reseller,
        'style=s'                   => \$style
      )
      and ( !@args )
      or do {
        usage();
        exit 1;
      };

    if ($help) {
        usage();
        exit;
    }

    unless ( $theme && ( $all_users || $users || $reseller ) ) {
        usage();
        exit 1;
    }

    my $theme_docroot = Cpanel::Themes::Utils::get_theme_root($theme);
    $logger->die( "The specified theme [" . $theme . "] does not exist." ) unless -d $theme_docroot;

    my $default_style_dir;

    if ($style) {
        $default_style_dir = get_default_style_dir( $style, $theme_docroot );
    }

    if ($reseller) {
        unless ( Cpanel::Reseller::isreseller($reseller) ) {
            $logger->die("'$reseller' is not a reseller.");
        }
    }

    local $ENV{'REMOTE_USER'} = 'root';

    Whostmgr::ACLS::init_acls();

    my %userdomains = Cpanel::Config::loadtrueuserdomains( undef, 1 );

    my @list_users;
    if ( $all_users || $reseller ) {
        @list_users = keys %userdomains;
        if ($reseller) {
            @list_users = grep { my $real_owner = Cpanel::AcctUtils::Owner::getowner($_); $real_owner && $real_owner eq $reseller ? 1 : 0 } @list_users;
        }
    }
    else {
        @list_users = split( /\s*,\s*/, $users );
    }

    my %updated_users;
    foreach my $user (@list_users) {
        unless ( exists $userdomains{$user} ) {
            $logger->warn("User: $user does not exist.");
            next;
        }

        if ($style) {
            $updated_users{$user} = update_user_style( $user, $default_style_dir );
            next;
        }

        if ( my $cpuser_guard = Cpanel::Config::CpUserGuard->new($user) ) {
            my $cpuser_data = $cpuser_guard->{'data'};
            $cpuser_data->{'RS'} = $theme;
            $cpuser_guard->save();
            Cpanel::Services::Cpsrvd::signal_users_cpsrvd_to_reload($user);

            $updated_users{$user} = 1;
        }
        else {
            $logger->warn("Unable to update data for $user.");
        }
    }

    my @failed_accts = grep { !$updated_users{$_} } @list_users;
    if ( scalar @failed_accts ) {
        $logger->warn( "Could not update these users: " . join( ', ', @failed_accts ) );
        exit 1;
    }
    else {
        $logger->info("Users are successfully updated.");
        exit 0;
    }
}

sub get_default_style_dir {
    my ( $style, $theme_docroot ) = @_;

    my ( $default_style_dir, $custom_style_dir );

    # style name can not start with a dot, prevents typo
    if ( $style eq 'current_style' || $style eq 'default_style' || $style =~ m/^\./ ) {
        $logger->die( "The specified style [" . $style . "] does not exist." );
    }

    $default_style_dir = $theme_docroot . 'styled/' . $style;
    $custom_style_dir  = get_custom_style_dir() . '/' . $style;

    if ( !-d $default_style_dir && !-d $custom_style_dir ) {
        $logger->die( "The specified style [" . $style . "] does not exist." );
    }

    if ( -d $custom_style_dir ) {
        $default_style_dir = $custom_style_dir;
    }

    return $default_style_dir;
}

sub get_custom_style_dir {
    return '/var/cpanel/customizations/styled';
}

sub update_user_style {
    my ( $user, $default_style_dir ) = @_;

    my $homedir   = ( Cpanel::PwCache::getpwnam($user) )[7];
    my $style_dir = $homedir . '/var/cpanel/styled';

    my $privs = Cpanel::AccessIds::ReducedPrivileges->new($user);

    File::Path::make_path( $style_dir, { mode => 0755 } ) unless -e $style_dir;
    unless ( -e $style_dir ) {
        $logger->warn("Unable to create user style directory: $style_dir");
        return 0;
    }

    unlink $style_dir . '/current_style';
    if ( -e $style_dir . '/current_style' ) {
        $logger->warn( "Unable to remove user current style: $style_dir" . '/current_style' );
        return 0;
    }

    symlink $default_style_dir, $style_dir . '/current_style';
    unless ( -l $style_dir . '/current_style' ) {
        $logger->warn( "Unable to assign user current style: $style_dir" . '/current_style' );
        return 0;
    }

    return 1;
}

sub usage {
    print <<"EOM";

modify_accounts: Modify existing accounts to use a theme or a style

Usage:
    modify_accounts --theme=paper_lantern [--users=user1,another_user|--all-users|--all-users-from-reseller=reseller1]

  Options:
    --help: print usage and exit
    --theme: the theme to be adopted
    --users: a list of users to be modified, comma separated
    --all-users: update all users on the system
    --all-users-from-reseller: update all users that are owned by reseller
    --style: update specified users to use this style
EOM
    return;
}

@KyuuKazami