#!/usr/bin/perl

#
# Copyright (C) 2017 Nethesis S.r.l.
# http://www.nethesis.it - support@nethesis.it
#
# This script is part of NethServer.
#
# NethServer is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License,
# or any later version.
#
# NethServer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with NethServer.  If not, see <http://www.gnu.org/licenses/>.
#

use strict;
use JSON;
use Encode;
use esmith::ConfigDB;
use NethServer::SSSD;
use DBI;
use NethServer::Password;

my $sssd = new NethServer::SSSD();
my $db = esmith::ConfigDB->open_ro() or die "Could not open config db";
my $domain = $db->get('DomainName')->prop('type');
my %settings = ();
my $security;
if ($sssd->port == 636) {
    $security = 'ssl';
} elsif ($sssd->startTls) {
    $security = 'tls';
}

my $password = decode('UTF-8',$sssd->bindPassword);

if ($sssd->isLdap) {
    $settings{'auth-settings'} = JSON->new()->ascii()->encode ({
        host => $sssd->host,
        port => $sssd->port,
        basedn => $sssd->baseDN,
        username => $sssd->bindDN,
        password => $password,
        displayname => 'gecos',
        userdn => 'ou=People',
        connection => $security,
        localgroups => '0',
        createextensions => '',
        externalidattr => 'entryUUID',
        descriptionattr => 'description',
        commonnameattr => 'uid',
        userobjectclass => 'posixAccount',
        userobjectfilter => '(&(objectclass=posixAccount)(!(uid=domguests))(!(uid=domcomputers))(!(uid=nsstest))(!(uid=locals))(!(uid=domadmins)))',
        usernameattr => 'uid',
        userfirstnameattr => 'givenName',
        userlastnameattr => 'sn',
        userdisplaynameattr => 'gecos',
        usertitleattr => '',
        usercompanyattr => '',
        usercellphoneattr => '',
        userworkphoneattr => 'telephoneNumber',
        userhomephoneattr => 'homephone',
        userfaxphoneattr => 'facsimileTelephoneNumber',
        usermailattr => 'mail',
        usergroupmemberattr => 'memberOf',
        la => '',
        groupnameattr => 'cn',
        groupdnaddition => 'ou=Groups',
        groupobjectclass => 'posixGroup',
        groupobjectfilter => '(objectclass=posixGroup)',
        groupmemberattr => 'memberUid',
        sync => '0 * * * *'
    });
    $settings{'driver'} = 'Openldap2';
    $settings{'name'} = 'NethServer LDAP';
} elsif($sssd->isAD) {
    $settings{'auth-settings'} = JSON->new()->ascii()->encode ({
        host => $sssd->host,
        port => $sssd->port,
        dn => $sssd->userDN,
        username => $sssd->bindUser,
        password => $password,
        domain => $db->get('sssd')->prop('Realm'),
        connection => $security,
        localgroups => '0',
        createextensions => '',
        externalidattr => 'objectGUID',
        descriptionattr => 'description',
        commonnameattr => 'cn',
        userdn => '',
        userobjectclass => 'user',
        userobjectfilter => '(&(objectClass=user)(objectCategory=person))',
        usernameattr => 'sAMAccountName',
        userfirstnameattr => 'givenName',
        userlastnameattr => 'sn',
        userdisplaynameattr => 'displayName',
        usertitleattr => 'personaltitle',
        usercompanyattr => 'company',
        usercellphoneattr => 'mobile',
        userworkphoneattr => 'telephoneNumber',
        userhomephoneattr => 'homephone',
        userfaxphoneattr => 'facsimileTelephoneNumber',
        usermailattr => 'mail',
        usergroupmemberattr => 'memberOf',
        la => '',
        groupdnaddition => '',
        groupobjectclass => 'group',
        groupobjectfilter => '(objectCategory=Group)',
        groupmemberattr => 'member',
        sync => '0 * * * *'
    });
    $settings{'driver'} = 'Msad2';
    $settings{'name'} = 'NethServer AD';
}

# Connect to asterisk mysql
my $mysqlpwd = NethServer::Password::store('mysql');
my $dbh = DBI->connect("DBI:mysql:database=asterisk;host=localhost","root",$mysqlpwd,{'RaiseError' => 1});

if ($sssd->isLdap or $sssd->isAD) {
    # Check if there is a NethServer AD or LDAP already configured and gets its id
    my $id;
    my $sth = $dbh->prepare("SELECT id,name,driver FROM `userman_directories` WHERE `name` LIKE 'NethServer LDAP%' OR `name` LIKE 'NethServer AD%'");
    $sth->execute();
    if (my $ref = $sth->fetchrow_hashref()) {
        $id = $ref->{'id'};
        if ((($ref->{'name'} eq 'NethServer LDAP') or ($ref->{'name'} eq 'NethServer AD')) and ($ref->{'driver'} ne 'Openldap')) {
            # Update configuration if name in NethServer LDAP or NethServer AD but LDAP driver isn't legacy Openldap
            my $sth = $dbh->prepare("UPDATE IGNORE kvstore_FreePBX_modules_Userman SET `key`='auth-settings', `val`=?,`type`='json-arr' WHERE `id`=?");
            $sth->execute( $settings{'auth-settings'},$id );
            $dbh->do("UPDATE IGNORE `userman_directories` SET `name`='" . $settings{'name'} . "',`driver`='" . $settings{'driver'} . "', `active`=1, `order`=5, `default`=1, `locked`=0 WHERE `name`='" . $ref->{'name'} . "'");
        } elsif (($ref->{'driver'} eq 'Openldap') and ($ref->{'name'} eq 'NethServer LDAP')) {
	    # Change driver name to NethServer LDAP legacy if directory is configured with LDAP legacy driver
	    $dbh->do("UPDATE IGNORE `userman_directories` SET `name`='NethServer LDAP legacy' WHERE `name`='" . $ref->{'name'} . "'");
	}
        $sth->finish();
    } else {
	# Directory isn't already configured, create a new configuration
        # Set defautl to 0 for other userman_directories
        $dbh->do("UPDATE IGNORE `userman_directories` SET `default` = 0");
        # Create entry for NethServer AD/LDAP in userman_directories
        $dbh->do("INSERT INTO `userman_directories` (`name`, `driver`, `active`, `order`, `default`, `locked`) VALUES ('" . $settings{'name'} . "','" . $settings{'driver'} . "',1,5,1,0)");
        $sth->finish();
        $sth->execute();
        $ref = $sth->fetchrow_hashref();
        $id = $ref->{'id'};
        $sth->finish();
        # Create configuration
        my $sth = $dbh->prepare("INSERT INTO kvstore_FreePBX_modules_Userman (`key`, `val`, `type`, `id`) VALUES ('auth-settings',?,'json-arr',?)");
        $sth->execute( $settings{'auth-settings'},$id );
    }
    $dbh->disconnect();

    system("/usr/bin/scl enable rh-php56 -- /usr/sbin/fwconsole userman --sync $id --force");

} else {
    # Remove Account Provider configuration
    my $sth = $dbh->prepare("DELETE FROM `userman_directories` WHERE `name` LIKE 'NethServer LDAP%' OR `name` LIKE 'NethServer AD%'");
    $sth->execute();

    system("/usr/bin/scl enable rh-php56 -- /usr/sbin/fwconsole userman --syncall --force --verbose");
}

# HACK: "fwconsole userman sync" will return 1 if there is no user insidethe the LDAP
my $ret = $? >> 8;
if ( $ret == 1) {
    $ret = 0;
}
exit($ret);

