#!/usr/bin/perl -w
# This script (sophomorix-session) is maintained by Rüdiger Beck
# It is Free Software (License GPLv3)
# If you find errors, contact the author
# jeffbeck@web.de  or  jeffbeck@linuxmuster.net

# modules
use strict;
#use Quota;
use Getopt::Long;
Getopt::Long::Configure ("bundling");
use Sophomorix::SophomorixConfig;
use List::MoreUtils qw(uniq);
use String::Approx 'amatch';
use String::Approx 'adist';
use Net::LDAP;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Terse = 1;
use JSON;
use File::Basename qw( basename
                       dirname
                     ); 
use Text::Iconv;
use Sophomorix::SophomorixBase qw(
                                 print_line
                                 print_title
                                 unlock_sophomorix
                                 lock_sophomorix
                                 log_script_start
                                 log_script_end
                                 log_script_exit
                                 backup_auk_file
                                 get_passwd_charlist
                                 get_plain_password
                                 check_options
                                 config_sophomorix_read
                                 result_sophomorix_init
                                 result_sophomorix_add
                                 result_sophomorix_check_exit
                                 result_sophomorix_print
                                 filelist_fetch
                                 remove_whitespace
                                 json_dump
                                 recode_utf8_to_ascii
                                 remove_from_list
                                 );
use Sophomorix::SophomorixSambaAD qw(
                                 AD_school_create
                                 AD_bind_admin
                                 AD_unbind_admin
                                 AD_session_manage
                                 AD_user_create
                                 AD_group_create
                                 AD_group_addmember
                                 AD_group_update
                                 AD_get_schoolname
                                 AD_get_name_tokened
                                 AD_dn_fetch_multivalue
                                 AD_get_sessions
                                 AD_dns_get
                                 AD_object_search
                                 AD_get_passwd
                                    );

my @arguments = @ARGV;

# option vars
$Conf::log_level=1;
my $help=0;
my $info=0;
my $json=0;

my $create=0;
my $kill=0;
my $kill_all_sessions=0;
my $kill_all_auto_generated_sessions=0;
my $supervisor="";
my $session="";
my $developer_session="";
my $comment;;
my $participants; # undef: do not change participants
my $add_participants="";
my $remove_participants="";
my $list_transfer_dirs=0;
my $list_quota=0;

# Parsen der Optionen
my $testopt=GetOptions(
           "help|h" => \$help,
           "info|i" => \$info,
           "json|j+" => \$json,
           "verbose|v+" => \$Conf::log_level,
           "create|c" => \$create,
           "kill" => \$kill,
           "kill-all-sessions" => \$kill_all_sessions,
           "kill-all-auto-generated-sessions" => \$kill_all_auto_generated_sessions,
           "supervisor=s" => \$supervisor,
           "session|s=s" => \$session,
           "comment=s" => \$comment,
           "participants|m=s" => \$participants,
           "add-participants=s" => \$add_participants,
           "remove-participants=s" => \$remove_participants,
           "developer-session=s" => \$developer_session,
           "list-transfer-dirs" => \$list_transfer_dirs,
           "list-quota" => \$list_quota,
          );

my %sophomorix_result=&result_sophomorix_init("sophomorix-session");
# Prüfen, ob Optionen erkannt wurden, sonst Abbruch
&check_options($testopt,\%sophomorix_result,$json);

# Reading Configuration
my ($ldap,$root_dse) = &AD_bind_admin(\@arguments,\%sophomorix_result,$json);
my $root_dns=&AD_dns_get($root_dse);
my %sophomorix_config=&config_sophomorix_read($ldap,$root_dse,\%sophomorix_result);
my ($smb_admin_pass)=&AD_get_passwd($DevelConf::sophomorix_file_admin,
                                     $DevelConf::secret_file_sophomorix_file_admin);
my @filelist=&filelist_fetch({filetype=>"users",
                              sophomorix_config=>\%sophomorix_config,
                            });
my %sessions=();


# --help
if ($help==1) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlsbeschreibung
   print('
sophomorix-session manages sessions

Options:
  -h  / --help
  -v  / --verbose
  -vv / --verbose --verbose

  -i  / --info 
    show sessions
  -ij 
    show sessions as JSON Object


  --supervisor <user>
  --comment <string>                      # ; are dropped in comment
    --comment ""                          # clear comment
  --participants <user1>,<user2>, ...
    --participants ""                     # clear participant list
  --add-participants <user1>,<user2>, ...
  --remove-participants <user1>,<user2>, ...
  --create (use current time as session-id)
  --kill -s <session-id>
  --kill-all-sessions
  --kill-all-auto-generated-sessions (created by schulkonsole)

Create a session with the current time:
  sophomorix-session --create --supervisor <user>
  sophomorix-session --create --supervisor <user> --participants <user1>,<user2>, ...

Update the participants of a running session:
  sophomorix-session --session <session_id> --participants <user1>,<user2>, ...



Dumping data:  
  -ij                                          (dump all sessions)
  -ij --supervisor <user>                      (dump all sessions of user <user>)
  -ij --session <session>                      (dump the session <session>)
  -ij --session <session> --list-transfer-dir  (dump the session <session> and list transfer dirs)
  -ij --session <session> --list-transfer-dir --list-quota  
       (dump the session <session>, list transfer dirs and quota)
  
  -j / --json                      (dump as a nice json object)
  -jj / --json --json              (dump as a compact json object)
  -jjj / --json --json --json      (dump as a perl hash)


Please see the sophomorix-session(8) man pages for full documentation
');
   print "\n";
   exit;
}

if ($supervisor ne ""){
    # get all sessions of user $supervisor 
    %sessions=&AD_get_sessions($ldap,$root_dse,$root_dns,$json,"all",$supervisor,$smb_admin_pass,$list_transfer_dirs,$list_quota,\%sophomorix_config);
} elsif ($session ne ""){
    # get the session $session
    %sessions=&AD_get_sessions($ldap,$root_dse,$root_dns,$json,$session,"allsupervisors",$smb_admin_pass,$list_transfer_dirs,$list_quota,\%sophomorix_config);
} else {
    # get all sessions of all supervisors
    %sessions=&AD_get_sessions($ldap,$root_dse,$root_dns,$json,"all","allsupervisors",$smb_admin_pass,$list_transfer_dirs,$list_quota,\%sophomorix_config);
}


# --info
if ($info==1) {
    my $jsoncomment;
    my $jsoninfo;
    if ($session ne ""){
        # show only one session
        $jsoninfo="ONESESSION";
        $jsoncomment="The sophomorix session $session";
    } else {
        # show all sessions
        $jsoninfo="SESSIONS";      
        $jsoncomment="All sophomorix sessions";
    }

    &json_dump({json => $json,
                jsoninfo => $jsoninfo,
                jsoncomment => $jsoncomment,
                object_name => $session,
                log_level => $Conf::log_level,
                hash_ref => \%sessions,
                sophomorix_config => \%sophomorix_config,
               });

    if ($session ne "" and exists $sessions{'ID'}{$session}{'SUPERVISOR'}{'sAMAccountName'}){
        print "\n";
        &Sophomorix::SophomorixBase::print_title("Session $session:");
        print "     *         supervisor:  $sessions{'ID'}{$session}{'SUPERVISOR'}{'sAMAccountName'}  (supervisor of the session)\n";
        print "     *       participants:  $sessions{'ID'}{$session}{'PARTICIPANTSTRING'}  (participants of the session)\n";
        print "     * sophomorixSessions:  $sessions{'ID'}{$session}{'sophomorixSessions'}\n";
    } 


    # supervisor listing
    if ($supervisor ne ""){
        my @ordered_list=();
        foreach my $session ( keys %{ $sessions{'SUPERVISOR'}->{$supervisor}{'sophomorixSessions'} }){
            push @ordered_list, $session;
        }
        @ordered_list = sort @ordered_list;
        my $count=0;
        print "\n";
        &Sophomorix::SophomorixBase::print_title("Sessions of supervisor $supervisor:");
        foreach my $session (@ordered_list ){
            $count++;
            print "  $count) Supervisor $supervisor session: $session\n";
            print "     *         supervisor:  $sessions{'ID'}{$session}{'SUPERVISOR'}{'sAMAccountName'}  (supervisor of the session)\n";
            print "     *       participants:  $sessions{'ID'}{$session}{'PARTICIPANTSTRING'}  (participants of the session)\n";
            print "     * sophomorixSessions:  $sessions{'ID'}{$session}{'sophomorixSessions'}\n";
        }
    }
    exit $sessions{'SESSIONCOUNT'};
}


&result_sophomorix_check_exit(\%sophomorix_result,\%sophomorix_config,$json);
################################################################################
# Start
################################################################################
&log_script_start(\@arguments,\%sophomorix_result,\%sophomorix_config);


if ($kill_all_sessions==1){
    &Sophomorix::SophomorixBase::print_title("Killing the following sessions:");
    foreach my $session (keys %{ $sessions{'ID'} }) {
        &AD_session_manage({ldap=>$ldap,
                            root_dse=>$root_dse,
                            session=>$session,
                            kill=>"TRUE",
                            create=>"FALSE",
                            sessions_ref=>\%sessions,
                            sophomorix_config=>\%sophomorix_config,
                        });
    }
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



if ($kill_all_auto_generated_sessions==1){
    foreach my $session (keys %{ $sessions{'AUTO_GENERATED_by_session'} }) {
        &AD_session_manage({ldap=>$ldap,
                            root_dse=>$root_dse,
                            session=>$session,
                            kill=>"TRUE",
                            create=>"FALSE",
                            sessions_ref=>\%sessions,
                            sophomorix_config=>\%sophomorix_config,
                           });
    }
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}


if ($session ne "" and $kill==1){
    # update the requested session
    &AD_session_manage({ldap=>$ldap,
                        root_dse=>$root_dse,
                        session=>$session,
                        kill=>"TRUE",
                        create=>"FALSE",
                        sessions_ref=>\%sessions,
                        sophomorix_config=>\%sophomorix_config,
                    });
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



if ($create==1 and $supervisor ne ""){
    # create a session in supervisor
    if (not defined $participants){
       $participants=""; 
    }   
    if (not defined $comment){
       $comment=""; 
    }   
    &AD_session_manage({ldap=>$ldap,
                        root_dse=>$root_dse,
                        supervisor=>$supervisor,
                        participants=>$participants,
                        comment=>$comment,
                        create=>"TRUE",
                        kill=>"FALSE",
                        developer_session=>$developer_session,
                        sessions_ref=>\%sessions,
                        sophomorix_config=>\%sophomorix_config,
                    });
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --participants
if ($session ne "" and defined $participants){
    # update the requested session
    &AD_session_manage({ldap=>$ldap,
                        root_dse=>$root_dse,
                        supervisor=>$supervisor,
                        create=>"FALSE",
                        kill=>"FALSE",
                        session=>$session,
                        participants=>$participants,
                        sessions_ref=>\%sessions,
                        sophomorix_config=>\%sophomorix_config,
                    });
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --comment
if ($session ne "" and defined $comment){
    # update the requested session
    &AD_session_manage({ldap=>$ldap,
                        root_dse=>$root_dse,
                        supervisor=>$supervisor,
                        create=>"FALSE",
                        kill=>"FALSE",
                        session=>$session,
                        comment=>$comment,
                        sessions_ref=>\%sessions,
                        sophomorix_config=>\%sophomorix_config,
                    });
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --add-participants
if ($session ne "" and $add_participants ne ""){
    my @add_participants=split(/,/,$add_participants);
    my @old_participants=split(/,/,$sessions{'ID'}{$session}{'PARTICIPANTSTRING'});
    my @participants = uniq(@old_participants,@add_participants);
    my $participants_new=join(",",@participants);
    # update the requested session
    &AD_session_manage({ldap=>$ldap,
                        root_dse=>$root_dse,
                        supervisor=>$supervisor,
                        create=>"FALSE",
                        kill=>"FALSE",
                        session=>$session,
                        participants=>$participants_new,
                        sessions_ref=>\%sessions,
                        sophomorix_config=>\%sophomorix_config,
                    });
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --remove-participants
if ($session ne "" and $remove_participants ne ""){
    my @old_participants=split(/,/,$sessions{'ID'}{$session}{'PARTICIPANTSTRING'});
    my @participants = &remove_from_list($remove_participants,@old_participants);
    my $participants_new=join(",",@participants);
    # update the requested session
    &AD_session_manage({ldap=>$ldap,
                        root_dse=>$root_dse,
                        supervisor=>$supervisor,
                        create=>"FALSE",
                        kill=>"FALSE",
                        session=>$session,
                        participants=>$participants_new,
                        sessions_ref=>\%sessions,
                        sophomorix_config=>\%sophomorix_config,
                    });
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}


&AD_unbind_admin($ldap);
&log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);

################################################################################
# Sub
################################################################################
