#!/usr/bin/perl -w
# This script (sophomorix-class) 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 Getopt::Long;
Getopt::Long::Configure ("bundling");
use Sophomorix::SophomorixConfig;
use List::MoreUtils qw(uniq);
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 Sophomorix::SophomorixBase qw(
                                 print_line
                                 print_title
                                 create_schoollist
                                 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
                                 remove_from_list
                                 json_dump
                                 );
use Sophomorix::SophomorixSambaAD qw(
                                 AD_school_create
                                 AD_bind_admin
                                 AD_dns_get
                                 AD_unbind_admin
                                 AD_user_create
                                 AD_get_user
                                 AD_group_create
                                 AD_group_kill
                                 AD_group_addmember
                                 AD_get_schoolname
                                 AD_get_name_tokened
                                 AD_class_fetch
                                 AD_group_update
                                 AD_project_sync_members
                                 AD_dn_fetch_multivalue
                                 AD_get_passwd
                                 AD_get_groups_v
                                 AD_get_full_groupdata
                                 AD_get_AD_for_check
                                    );
my @arguments = @ARGV;

# classtype
my $class_type="adminclass"; # default is adminclass

# update teachers groups in classes
my $update_teachers_groups = 0;

############################################################
# Option handling
############################################################
my %options=();
# define possible action in a script and what OBJECT they need
$options{'CONFIG'}{'ACTION'}{'GROUP'}="create,".
                                      "kill,".
                                      "description,".
                                      "quota,".
                                      "mailquota,".
                                      "status,".
                                      "maxmembers,".
                                      "creationdate,".
                                      "gidnumber-migrate,".
                                      "mailalias,".
                                      "maillist,".
                                      "join,".
                                      "hide,".
                                      "admins,".
                                      "addadmins,".
                                      "removeadmins,".
                                      "members,".
                                      "addmembers,".
                                      "removemembers";
# define which options deliver which object
$options{'CONFIG'}{'ONE_OF'}{'GROUP'}="class";
$options{'CONFIG'}{'SINGLE'}{'ACTION'}="delete-all-empty-classes,delete-all-teacheronly-classes,update-maildomain,remove-student-admins-from-class";
# define option that can modify which object
$options{'CONFIG'}{'MAYBE'}{'GROUP'}="all,".
                                     "teacherclass,".
                                     "adminclass,".
                                     "extraclass,";
# define more dependencies
$options{'CONFIG'}{'DEPENDS'}{'gidnumber-migrate'}="create";
$options{'CONFIG'}{'DEPENDS'}{'skip-school-creation'}="create";

my $testopt=GetOptions(\%options, 
                       "help|h",
                       "info|i",
                       "json|j+",
                       "verbose|v+",
                       "class|c=s",
                       "all",
                       "adminclass",
                       "teacherclass",
                       "extraclass",
                       "create",
                       "gidnumber=i",
                       "kill",
                       "skip-school-creation",
                       "school=s",
                       "description=s",
                       "quota=s",
                       "mailquota=s",
                       "status=s",
                       "maxmembers=s",
                       "creationdate=s",
                       "gidnumber-migrate=i",
                       "mailalias!",
                       "maillist!",
                       "join!",
                       "hide!",
                       "admins=s",
                       "addadmins=s",
                       "removeadmins=s",
                       "members=s",
                       "addmembers=s",
                       "removemembers=s",
                       "delete-all-empty-classes",
                       "delete-all-teacheronly-classes",
                       "update-maildomain",
		       "remove-student-admins-from-class",
                      );    

my %sophomorix_result=&result_sophomorix_init("sophomorix-class");
# Prüfen, ob Optionen erkannt wurden
&check_options($testopt,\%sophomorix_result,$options{'json'},\%options);

# defaults
if (not defined $options{'gidnumber-migrate'}){
    $options{'gidnumber-migrate'}="---";
}
if (not defined $options{'school'}){
    $options{'school'}="---";
}

print Dumper (\%options);


# Reading Configuration
my ($ldap,$root_dse) = &AD_bind_admin(\@arguments,\%sophomorix_result,$options{'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);

# calculate $class_type
if (defined $options{'teacherclass'}){
    $class_type="teacherclass";
}
if (defined $options{'extraclass'}){
    $class_type="extraclass";
}
if (defined $options{'adminclass'}){
    $class_type="adminclass";
}
if (defined $options{'all'}){
    $class_type="class";
}



# --help
#if ($help==1) {
if (defined $options{'help'}) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlbeschreibung
   print('
sophomorix-class sets properties of a class in the database

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

  -i  / --info          (Default: displays adminclass only)
  -i --adminclass       (displays adminclass)
  -i --teacherclass     (displays teacherclass)
  -i --extraclass       (displays extraclass)
  -i --all              (displays adminclass/teacherclass/extraclass)

Changing one/multiple admin-/extra-/teacherclass:
  -c <class>,<class2>,... / --class <class1>,<class2>,... 
  (can set values also for the group teachers with --class teachers)
    --description \'multiple words possible\'
    --quota <share1>:<quota1 in MiB>:<comment1>,<share2>:<quota2 in MiB>:<comment2>,...
    --mailquota <mailquota in MiB>:<Comment>
    --mailalias, --nomailalias
    --maillist, --nomaillist 
    --status <P,M> (P=Permanent or M=Managed)
    --join,  --nojoin
    --hide,  --nohide
    --maxmembers number

    --admins user1,user2,user3, ... 
    --addadmins user1,user2,user3, ...
    --removeadmins user1,user2,user3, ...

    For administrators:
    --remove-student-admins-from-class --info   (show which users are removed as admin)
    --remove-student-admins-from-class          (do it)

Updating changes from school.conf
    --update-maildomain  (for all schools)

This is for migration/testing/fixing only (only one class allowed as option):
  --create --skip-school-creation --class <class> --gidnumber-migrate <num>
  --creationdate <20150529093330.0Z> (only for migration)
  --gidnumber-migrate <num>
  --members user1,user2,user3, ... 
  --addmembers user1,user2,user3, ...
  --removemembers user1,user2,user3, ...


Be careful with this commands:
  Delete empty (no students and no teachers) classes (status must be M):
    --delete-all-empty-classes
  Delete classes with only teachers (no students) as members (class status must be M):
    --delete-all-teacheronly-classes
  Delete a class unconditionally (This deletes a class even if the status is P):
    --kill --class <class>,<class2>,...


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


# --school <school1,school2, ...>
my @opt_schoollist=&create_schoollist($options{'school'},\%sophomorix_config);



############################################################
# config values
############################################################

# --info
# show all class when no specific class is given
if ($options{'info'}==1 and not
    defined $options{'class'} and not
    defined $options{'remove-student-admins-from-class'}
   ){
    my $ref_group_v=&AD_get_groups_v({ldap=>$ldap,
                                   root_dse=>$root_dse,
                                   root_dns=>$root_dns,
                                   school=>$options{'school'},
                                   sophomorix_config=>\%sophomorix_config,
                                 });
  
    #print Dumper($ref_group_v->{'LISTS'});
    my $jsoninfo="CLASSES_OVERVIEW";
    my $jsoncomment="All Groups";
    &json_dump({json => $options{'json'},
                jsoninfo => $jsoninfo,
                jsoncomment => $jsoncomment,
                object_name => $options{'school'},
                type => $class_type,
                log_level => $options{'verbose'},
                hash_ref => $ref_group_v,
                sophomorix_config => \%sophomorix_config,
               });
   exit;
}



# --info --class <name>
# list class(es) and exit
if ($options{'info'}==1 and defined $options{'class'}){
   my $ref_groups=&AD_get_full_groupdata({ldap=>$ldap,
                                           root_dse=>$root_dse,
                                           root_dns=>$root_dns,
                                           grouplist=>$options{'class'},
                                           sophomorix_config=>\%sophomorix_config,
                                      });
    #print Dumper($ref_groups);
    my $jsoninfo="CLASS";
    my $jsoncomment="Class";
    &json_dump({json => $options{'json'},
                jsoninfo => $jsoninfo,
                jsoncomment => $jsoncomment,
                object_name => $options{'school'},
                log_level => $options{'verbose'},
                hash_ref => $ref_groups,
                sophomorix_config => \%sophomorix_config,
               });
    exit;
}



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



# --update-maildomain
if (defined $options{'update-maildomain'}){
    my $ref_group_v=&AD_get_groups_v({ldap=>$ldap,
                                   root_dse=>$root_dse,
                                   root_dns=>$root_dns,
                                   school=>$options{'school'},
                                   sophomorix_config=>\%sophomorix_config,
				     });
    #print Dumper($ref_group_v);
    foreach my $school (@opt_schoollist){
	foreach my $class (@{ $ref_group_v->{'LISTS'}{'GROUP_by_sophomorixSchoolname'}{$school}{'class'} }){
	    my $type=$ref_group_v->{'GROUPS'}{$class}{'sophomorixType'};
	    my $dn=$ref_group_v->{'GROUPS'}{$class}{'DN'};
	    my $mail = $class."\@".$root_dns;
	    my $maildomain_key;
            if ($school eq $DevelConf::name_default_school){
                $maildomain_key=$type;
            } else {
                $maildomain_key=$school."-".$type;
            }
	    if (exists $sophomorix_config{'TYPES'}{$maildomain_key}{'MAILDOMAIN'}){
                if ($sophomorix_config{'TYPES'}{$maildomain_key}{'MAILDOMAIN'} ne ""){
                    $mail=$class."\@".
                    $sophomorix_config{'TYPES'}{$maildomain_key}{'MAILDOMAIN'};
	        }
            }
	    &AD_group_update({ldap=>$ldap,
                              root_dse=>$root_dse,
                              dn=>$dn,
                              school=>$school,
                              type=>$type,
                              mail=>$mail,
                              sophomorix_config=>\%sophomorix_config,
                            });
	}
    }
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});
}



# --delete-all-empty-classes / --delete-all-teacheronly-classes
if (defined $options{'delete-all-empty-classes'} or defined $options{'delete-all-teacheronly-classes'}){
    my @to_delete=();
    my $ref_group_v=&AD_get_groups_v({ldap=>$ldap,
                                   root_dse=>$root_dse,
                                   root_dns=>$root_dns,
                                   school=>$options{'school'},
                                   sophomorix_config=>\%sophomorix_config,
                                 });

    my $line1="------------------------------------------------------------\n";
    my $line2="############################################################\n";
    foreach my $school (@opt_schoollist){
        print $line1;
        print "Looking for adminclasses in school $school:\n";
        foreach my $adminclass (@{ $ref_group_v->{'LISTS'}{'GROUP_by_sophomorixSchoolname'}{$school}{'adminclass'} }){
            my $ref_groups=&AD_get_full_groupdata({ldap=>$ldap,
                                                   root_dse=>$root_dse,
                                                   root_dns=>$root_dns,
                                                   grouplist=>$adminclass,
                                                   sophomorix_config=>\%sophomorix_config,
                                                 });

            if (exists $ref_groups->{'GROUPS'}{$adminclass}{'member'}){
                # membership can be determined
                my $member_count=$#{ $ref_groups->{'GROUPS'}{$adminclass}{'member'} }+1;
                my $status=$ref_group_v->{'GROUPS'}{$adminclass}{'sophomorixStatus'};

                my $ref_groups=&AD_get_full_groupdata({ldap=>$ldap,
                                                       root_dse=>$root_dse,
                                                       root_dns=>$root_dns,
                                                       grouplist=>$adminclass,
                                                       sophomorix_config=>\%sophomorix_config,
                                                     });
                # Test if all members are teachers
                if($Conf::log_level>=2){
                    print "* $adminclass: Testing members\n";
                }
                my $not_teacher_count=0;
                my $count=0;
                foreach my $member ( @{ $ref_groups->{'GROUPS'}{$adminclass}{'member'} } ){
                    $count++;
                    my ($sam,@unused)=split(/,/,$member);
                    $sam=~s/^CN=//g; # remove leading CN=
                    my ($firstname_utf8_AD,$lastname_utf8_AD,$adminclass_AD,$existing_AD,$exammode_AD,$role_AD,
                        $home_directory_AD,$user_account_control_AD,$toleration_date_AD,$deactivation_date_AD,
                        $school_AD,$status_AD,$firstpassword_AD,$unid_AD)=
                        &AD_get_user({ldap=>$ldap,
                                      root_dse=>$root_dse,
                                      root_dns=>$root_dns,
                                      user=>$sam,
                                    });
                        if  ($role_AD ne $sophomorix_config{'INI'}{'ROLE_USER'}{'TEACHER'}){
                            if($Conf::log_level>=2){
                                print "    $count) $sam is a $role_AD (not a $sophomorix_config{'INI'}{'ROLE_USER'}{'TEACHER'})\n";
                            }
                            $not_teacher_count++;
                        } else {
                            if($Conf::log_level>=2){
                                print "    $count) $sam is a $role_AD\n";
                            }
                        }
                }

                # conclusions from above queries
                if ($status eq "M"){
                    if (defined $options{'delete-all-empty-classes'}){
                        if ($member_count==0){
                            # delete empty class
                            print "  -> $adminclass has $member_count members: $adminclass can be deleted!\n";
                            push @to_delete,$adminclass;
                        } else {
                            print "  -> $adminclass has still $member_count member(s): Not deleting!\n";
                        }
		    } elsif (defined $options{'delete-all-teacheronly-classes'}){
                        if ($not_teacher_count==0){
                            # delete teachers only class
                            print "  -> $adminclass has only teachers as members: $adminclass can be deleted!\n";
                            push @to_delete,$adminclass;
                        } else {
                            print "  -> $adminclass ($status) has $not_teacher_count non-teacher(s) as members: Not deleting!\n";
                        }
		    }
                } elsif ($status eq "P") {
                    if (defined $options{'delete-all-empty-classes'}){
                        if ($member_count==0){
                            print "  -> $adminclass has $member_count members but is permanent ($status): Not deleting!\n";
                        } else {
                            print "  -> $adminclass has $member_count member(s) and is permanent ($status): Not deleting!\n";
                        }
		    } elsif (defined $options{'delete-all-teacheronly-classes'}){
                        if ($not_teacher_count==0){
                            print "  -> $adminclass has only teachers as members but is permanent ($status): Not deleting!\n";
                        } else {
                            print "  -> $adminclass has $not_teacher_count non-teacher(s) as members ".
                                  "and is permanent ($status): Not deleting!\n";
                        }
                    }
                } else {
                    print "  -> $adminclass has unkown status $status! Doing nothing!\n";
                }

            } else {
                # membership unknown
                print "\nERROR: adminclass $adminclass not found to count members!\n\n";
                exit 88;
            }
        }
        print $line1;
        print "\n";
    }

    ############################################################
    # do it!
    print $line2;
    my $delete_count=$#to_delete+1;
    print "I'm deleting permanently the following $delete_count adminclasses:\n\n";
    foreach my $adminclass (@to_delete){
        print "    $adminclass will be DELETED permanently!\n";
    }
    print "\n$delete_count adminclasses will be DELETED permanently!\n";
    print $line2;
    print "\nYou have 10 seconds to abort with Ctrl+c\n\n";
    sleep 10;

    foreach my $adminclass (@to_delete){
        &AD_group_kill({ldap=>$ldap,
                        root_dse=>$root_dse,
                        root_dns=>$root_dns,
                        group=>$adminclass,
                        smb_admin_pass=>$smb_admin_pass,
                        type=>"adminclass",
                        sophomorix_config=>\%sophomorix_config,
                      });
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});
}


# --remove-student-admins-from-class
if (defined $options{'remove-student-admins-from-class'}){
    my $ref_group_v=&AD_get_groups_v({ldap=>$ldap,
                                   root_dse=>$root_dse,
                                   root_dns=>$root_dns,
                                   school=>$options{'school'},
                                   sophomorix_config=>\%sophomorix_config,
				     });

    # fetch AD data
    my ($ref_AD_check) = &AD_get_AD_for_check({ldap=>$ldap,
                                           root_dse=>$root_dse,
                                           root_dns=>$root_dns,
                                           admins=>"FALSE",
                                           sophomorix_config=>\%sophomorix_config,
                                         });

    foreach my $school (@opt_schoollist){
	print "##################################################################################\n";
        print "##### Looking for students as class-admins in school $school #####\n";
	print "##################################################################################\n";
        foreach my $adminclass (@{ $ref_group_v->{'LISTS'}{'GROUP_by_sophomorixSchoolname'}{$school}{'adminclass'} }){
            my $ref_groups=&AD_get_full_groupdata({ldap=>$ldap,
                                                   root_dse=>$root_dse,
                                                   root_dns=>$root_dns,
                                                   grouplist=>$adminclass,
                                                   sophomorix_config=>\%sophomorix_config,
						  });
	    foreach my $admin ( @{ $ref_groups->{'GROUPS'}{$adminclass}{'sophomorixAdmins'} }){
		my $role=$ref_AD_check->{'sAMAccountName'}{$admin}{'sophomorixRole'};
		my $display_name=$ref_AD_check->{'sAMAccountName'}{$admin}{'displayName'};
		if ($role eq "student"){
		    my $command="sophomorix-class --removeadmins $admin -c $adminclass";
		    if ($options{'info'}==0){
			my $return=system("$command > /dev/null");
			if ($return==0){
			    print "  * SUCCESS: $command\n";
			} else {
			    print "  * FAILED: $command\n";
			}
		    } else {
			print "  INFO: student $admin must be removed from $adminclass: $command\n";
		    }
		}
	    }
	}
	print "##################################################################################\n";
    }

    #print Dumper ($ref_group_v);
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});
}



############################################################
# nonexisting class action:
# --create --class <name> --class <class1>,<class2>,...
############################################################
if (defined $options{'create'} and defined $options{'class'}){
    my @classes_option=split(/,/,$options{'class'});
    foreach my $class_option (@classes_option){
        if (defined $options{'skip-school-creation'}){
            # do nothing
        } else {
            &AD_school_create({ldap=>$ldap,
                               root_dse=>$root_dse,
                               root_dns=>$root_dns,
                               school=>$options{'school'},
                               smb_admin_pass=>$smb_admin_pass,
                               sophomorix_config=>\%sophomorix_config,
                               sophomorix_result=>\%sophomorix_result,
                             });
        }
        my $group_token=&AD_get_name_tokened($class_option,$options{'school'},$class_type);
        &AD_group_create({ldap=>$ldap,
                          root_dse=>$root_dse,
                          root_dns=>$root_dns,
                          school=>$options{'school'},
                          group=>$group_token,
                          group_basename=>$class_option,
                          description=>$group_token,
                          type=>$class_type,
                          status=>"P",
	   	          sub_ou=>"OU=".$class_option.",".$sophomorix_config{'INI'}{'OU'}{'AD_student_ou'},
                          joinable=>"TRUE",
                          hidden=>"FALSE",
                          gidnumber_migrate=>$options{'gidnumber-migrate'},
                          smb_admin_pass=>$smb_admin_pass,
                          sophomorix_config=>\%sophomorix_config,
                          sophomorix_result=>\%sophomorix_result,
                        });
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});
}



############################################################
# existing class action:
# get dn if class exists and continue ($info=0)
############################################################
my @classes_option=split(/,/,$options{'class'});
my %classes=();
foreach my $class_option (@classes_option){
    my $class_token=&AD_get_name_tokened($class_option,$options{'school'},$class_type);
    my ($dn_class,
        $count,
        $school_AD)=&AD_class_fetch($ldap,
                                $root_dse,
                                $class_token,
                                $options{'school'},
                                $class_type,
                                \%sophomorix_config,
                               );
    if ($count==1){
        $classes{'CLASS_VALID_DATA'}{$class_token}{'DN'}=$dn_class;
        $classes{'CLASS_VALID_DATA'}{$class_token}{'COUNT'}=$count;
        $classes{'CLASS_VALID_DATA'}{$class_token}{'SCHOOL'}=$school_AD;
        # push in the list of valid classes
        push @{ $classes{'CLASS_VALID_LIST'} }, $class_token;
    } else {
        print "Skipping class $class_token ($count matching classes found)\n";
        push @{ $classes{'CLASS_UNVALID_LIST'} }, $class_token;
        print "\nERROR retrieving class $options{'class'}: $count class found.\n\n";
        &log_script_exit("ERROR retrieving class $class_token: $count class found.",$count,1,0,
                         \@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});
    }
}



##################################################
# ??? --sync_all_memberships for classes? ???



# --description <strg> --class <class1>,<class2>,...
if (defined $options{'description'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          description=>$options{'description'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --quota <strg> --class <class1>,<class2>,...
if (defined $options{'quota'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
	       	          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          quota=>$options{'quota'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --mailquota <strg>
if (defined $options{'mailquota'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          mailquota=>$options{'mailquota'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --mailalias/nomailalias --class <class1>,<class2>,...
if (defined $options{'mailalias'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          mailalias=>$options{'mailalias'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --maillist/--nomaillist --class <class1>,<class2>,...
if (defined $options{'maillist'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          maillist=>$options{'maillist'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --status <P,M> --class <class1>,<class2>,...
if (defined $options{'status'}){
    if ($options{'status'} ne "P" and $options{'status'} ne "M"){
        &log_script_exit("Status $options{'status'} not allowed for classes",1,1,0,
                         \@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});

    }
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          status=>$options{'status'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --join/--nojoin --class <class1>,<class2>,...
if (defined $options{'join'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          join=>$options{'join'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --hide/--nohide
if (defined $options{'hide'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          hide=>$options{'hide'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --maxmembers <strg> --class <class1>,<class2>,...
if (defined $options{'maxmembers'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          maxmembers=>$options{'maxmembers'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --creationdate <strg> --class <class1>,<class2>,...
if (defined $options{'creationdate'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          creationdate=>$options{'creationdate'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --gidnumber-migrate <num>
if (defined $options{'gidnumber-migrate'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          gidnumber=>$options{'gidnumber-migrate'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



##################################################
# members
# --members <user1,user2> --class <class1>,<class2>,...
if (defined $options{'members'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          members=>$options{'members'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}


 
# --addmembers <user1,user2> --class <class1>,<class2>,...
if (defined $options{'addmembers'}){
    my @addmembers=split(/,/,$options{'addmembers'});
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        my @old_members = &AD_dn_fetch_multivalue($ldap,
                                                  $root_dse,
                                                  $classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                                                  "sophomorixMembers");
        my @members = uniq(@old_members,@addmembers); 
        my $members=join(",",@members);
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          members=>$members,
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}


 
# --removemembers <user1,user2> --class <class1>,<class2>,...
if (defined $options{'removemembers'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        my @old_members = &AD_dn_fetch_multivalue($ldap,
                                                  $root_dse,
                                                  $classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                                                  "sophomorixMembers");
        my @members = &remove_from_list($options{'removemembers'},@old_members);
        my $members=join(",",@members);
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          members=>$members,
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



##################################################
# admins
# --admins <user1,user2> --class <class1>,<class2>,...
if (defined $options{'admins'}){
    $update_teachers_groups = 1;
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          admins=>$options{'admins'},
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --addadmins <user1,user2> --class <class1>,<class2>,...
if (defined $options{'addadmins'}){
    $update_teachers_groups = 1;
    my @addadmins=split(/,/,$options{'addadmins'});
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        my @old_admins = &AD_dn_fetch_multivalue($ldap,
                                                 $root_dse,
                                                 $classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                                                 "sophomorixAdmins");
        my @admins = uniq(@old_admins,@addadmins); 
        my $admins=join(",",@admins);
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          admins=>$admins,
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}



# --removeadmins <user1,user2> --class <class1>,<class2>,...
if (defined $options{'removeadmins'}){
    $update_teachers_groups = 1;
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        my @old_admins = &AD_dn_fetch_multivalue($ldap,
                                                 $root_dse,
                                                 $classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
                                                 "sophomorixAdmins");
        my @admins = &remove_from_list($options{'removeadmins'},@old_admins);
        my $admins=join(",",@admins);
        &AD_group_update({ldap=>$ldap,
                          root_dse=>$root_dse,
                          dn=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'DN'},
		          school=>$classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'},
                          type=>$class_type,
                          admins=>$admins,
                          sophomorix_config=>\%sophomorix_config,
                        });
    }
}

# Update teachers groups like 8a-teachers if adminlists has changed (--removeadmins, --addadmins, --admins)
if ($update_teachers_groups == 1){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }) {
        system("/usr/sbin/lmncli -c $class_valid --sync-teachers -s $classes{'CLASS_VALID_DATA'}{$class_valid}{'SCHOOL'}");
    }
}

# --kill --class <class1>,<class2>,...
if (defined $options{'kill'} and defined $options{'class'}){
    foreach my $class_valid (@{ $classes{'CLASS_VALID_LIST'} }){
        &AD_group_kill({ldap=>$ldap,
                        root_dse=>$root_dse,
                        root_dns=>$root_dns,
                        group=>$class_valid,
                        smb_admin_pass=>$smb_admin_pass,
                        type=>$class_type,
                        sophomorix_config=>\%sophomorix_config,
                      });
    }
}


############################################################
# End
############################################################
&AD_unbind_admin($ldap);
&log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$options{'json'});







