Files
sogo/Scripts/sogo-user.pl
Wolfgang Sourdeau 8aae87afd5 Monotone-Parent: f6d4ca8944c94273bc0dae0565c60e45be9f2ca1
Monotone-Revision: 98896091d472e0ee7990f69f32f5981f5d1dc546

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-01-16T18:46:32
Monotone-Branch: ca.inverse.sogo
2008-01-16 18:46:32 +00:00

293 lines
8.9 KiB
Perl
Executable File

#/usr/bin/perl
# TODO:
# - partial delete: appointment tables only, contact tables only
# - stats: nb of calendars, nb of events, nb of events with
# participants, nb of recurrent events, nb of contacts, nb of
# addressbooks, nb of contacts, etc
=head1 NAME
sogo-user
=head1 SYNOPSIS
create-ldap-fburl [options] username ...
Options:
-help brief help message
-c, --config=FILE read configuration from FILE
-i, --info show information on the user
--delete delete user from SOGo databases
--fburl update Free-Busy URL in LDAP directory
-v, --verbose be verbose
=head1 DESCRIPTION
Apply various operations on a user with respect to her/his
SOGo environment.
=head1 AUTHOR
=over
=item Francis Lachapelle <flachapelle@inverse.ca>
=head1 COPYRIGHT
Copyright (c) 2007 Inverse groupe conseil
This program is available under the GPL.
=cut
#use diagnostics;
use strict;
use warnings;
use Config::IniFiles;
#use Data::Dumper;
use DBI;
use Getopt::Long qw(:config bundling);
#use Log::Log4perl;
use Net::LDAP;
use Pod::Usage;
use constant {
CONF_FILE => "sogo.conf"
};
my $help = '';
my $configfile = CONF_FILE;
my $info = '';
my $delete = '';
my $fburl = '';
my $verbose = '';
GetOptions(
"help|?" => \$help,
"config|c=s" => \$configfile,
"info|i" => \$info,
"delete" => \$delete,
"fburl" => \$fburl,
"verbose|v" => \$verbose
) or pod2usage( -verbose => 1);
pod2usage( -verbose => 2) if $help;
pod2usage( -verbose => 1) unless ($help || $info || $delete || $fburl);
pod2usage( -verbose => 1) if ($#ARGV < 0);
my $config;
my $dbh;
my $ldap;
$config = new Config::IniFiles( -file => $configfile, -nocase => 1);
die "ERROR: Can't read configuration file $configfile: $!\n" unless $config;
die "ERROR: Missing \"url\" in section [sogo]\n" unless ($config->val('sogo', 'url'));
# Verify LDAP parameters
foreach ('host', 'port', 'binddn', 'password', 'searchbase', 'uid_attr', 'mail_attr', 'fburl_attr') {
unless ($config->val('ldap', $_)) {
die "ERROR: Missing value for parameter \"$_\" in section [ldap].\n";
}
}
# Verify DB parameters
foreach ('uri', 'username', 'password') {
unless ($config->val('database', $_)) {
die "ERROR: Missing value for parameter \"$_\" in section [database].\n";
}
}
##
# Functions
sub initDatabase
{
$dbh = DBI->connect($config->val('database', 'uri'),
$config->val('database', 'username'),
$config->val('database', 'password'),
{ AutoCommit => 1, PrintError => 0 }) or die "ERROR: Can't connect to database: $DBI::errstr\n";
}
sub initLdap
{
$ldap = new Net::LDAP($config->val('ldap', 'host'))
or die "ERROR: Can't connect to ldap: $@\n";
my $msg = $ldap->bind($config->val('ldap', 'binddn'),
password => $config->val('ldap', 'password'));
if ($msg->is_error()) {
die "ERROR: Can't bind to ldap: ".$msg->error()."\n";
}
}
sub info
{
my $username = shift;
my $results;
my @entries;
my $hash_ref;
&initLdap() unless $ldap;
&initDatabase() unless $dbh;
# Fetch LDAP attributes
$results = $ldap->search(base => $config->val('ldap', 'searchbase'),
scope => 'sub',
attrs => [$config->val('ldap', 'uid_attr'),
$config->val('ldap', 'mail_attr'),
$config->val('ldap', 'fburl_attr')],
filter => sprintf('(%s=%s)', $config->val('ldap', 'uid_attr'), $username));
if ($results->is_error()) {
die "ERROR: Can't perform ldap search: ",$results->error(),"\n";
}
@entries = $results->entries;
die "ERROR: Unknown user $username\n" if ($#entries < 0);
foreach my $entry (@entries) {
print "Username: ", $entry->get_value( $config->val('ldap', 'uid_attr') ), "\n";
print "Mail: ", $entry->get_value( $config->val('ldap', 'mail_attr') ), "\n";
print "Freebusy URL: ", $entry->get_value( $config->val('ldap', 'fburl_attr') ) || "(undefined)", "\n";
}
# Retrive database tables information
$hash_ref = $dbh->selectall_hashref("select c_folder_id, c_folder_type, c_location, c_quick_location, c_acl_location from sogo_folder_info where c_path2 = ?", ($config->val('database', 'uri') =~ /^dbi:Pg/)?'c_folder_id':'C_FOLDER_ID', undef, ($username))
or die "Can't execute select statement: $DBI::errstr\n";
print "Tables:\n";
foreach my $id (keys %{$hash_ref}) {
print "\tType ", ($hash_ref->{$id}->{'C_FOLDER_TYPE'} || $hash_ref->{$id}->{'c_folder_type'})
, ", ID ", $id, "\n";
foreach my $col ('C_LOCATION', 'C_QUICK_LOCATION', 'C_ACL_LOCATION') {
print "\t\t", ($hash_ref->{$id}->{$col} || $hash_ref->{$id}->{lc($col)}), "\n";
}
}
print "\t(no table found)\n" unless (%{$hash_ref});
}
sub delete
{
my $username = shift;
my $hash_ref;
&initDatabase() unless $dbh;
# Select entries from sogo_folder_info
$hash_ref = $dbh->selectall_hashref("select C_UID from sogo_user_profile where C_UID = ?",
($config->val('database', 'uri') =~ /^dbi:Pg/)?'c_uid':'C_UID',
undef, ($username))
or die "ERROR: Can't execute select statement: $DBI::errstr\n";
if (%{$hash_ref}) {
# Delete entries from sogo_user_profile
$dbh->do("delete from sogo_user_profile where c_uid = ?", undef, ($username))
or die "ERROR: Can't delete entries from sogo_user_profile: $DBI::errstr\n";
}
else {
warn "No entries in sogo_user_profile\n";
}
# Select entries from sogo_folder_info
$hash_ref = $dbh->selectall_hashref("select c_folder_id, c_folder_type, c_location, c_quick_location, c_acl_location from sogo_folder_info where c_path2 = ?", ($config->val('database', 'uri') =~ /^dbi:Pg/)?'c_folder_id':'C_FOLDER_ID', undef, ($username))
or die "Can't execute select statement: $DBI::errstr\n";
if (%{$hash_ref}) {
# Delete entries from sogo_folder_info
$dbh->do("delete from sogo_folder_info where c_path2 = ?", undef, ($username))
or die "Can't delete entries from sogo_info_folder: $DBI::errstr\n";
}
else {
die "No entries in sogo_folder_info\n";
}
# Drop tables
foreach my $id (keys %{$hash_ref}) {
print "Folder ID $id, type ",($hash_ref->{$id}->{'C_FOLDER_TYPE'} || $hash_ref->{$id}->{'c_folder_type'}),"\n";
foreach my $col ('C_LOCATION', 'C_QUICK_LOCATION', 'C_ACL_LOCATION') {
$col = lc($col) unless ($hash_ref->{$id}->{$col});
if ($hash_ref->{$id}->{$col} =~ m#([^:]+)://([^:]+):([^@]+)@([^:]+):([^/]+)/([^/]+)/([^/]+)#) {
my ($type, $username, $password, $host, $port, $db, $table) = ($1, $2, $3, $4, $5, $6, $7);
my $uri;
print "Dropping ",$hash_ref->{$id}->{$col},"\n";
$uri = 'dbi:Pg:host=%s;port=%s;dbname=%s' if ($type eq 'http');
$uri = 'dbi:Oracle:host=%s;port=%s;sid=%s' if ($type eq 'oracle');
my $s = DBI->connect(sprintf($uri, $host, $port, $db), $username, $password, { AutoCommit => 1, PrintError => 0 }) or die "\tCan't connect: $!\n";
$s->do("drop table $table") or warn "\tERROR: Can't drop table $table: $DBI::errstr\n";
$s->disconnect();
}
}
}
}
sub fburl
{
my $username = shift;
my $results;
my @entries;
my $modified = '';
&initLdap() unless $ldap;
$results = $ldap->search(base => $config->val('ldap', 'searchbase'),
scope => 'sub',
attrs => ['objectClass',
$config->val('ldap', 'uid_attr'),
$config->val('ldap', 'mail_attr'),
$config->val('ldap', 'fburl_attr')],
filter => sprintf('(%s=%s)', $config->val('ldap', 'uid_attr'), $username));
if ($results->is_error()) {
die "ERROR: Can't perform ldap search: ",$results->error(),"\n";
}
@entries = $results->entries;
die "ERROR: Unknown user $username\n" if ($#entries < 0);
foreach my $entry (@entries) {
my $caldav_objectclass = $config->val('ldap', 'caldav_objectclass');
if (length($caldav_objectclass) > 0) {
# Add objectClass if not present
my @objectClasses = $entry->get_value('objectClass');
#print "classes = ", join(", ", @objectClasses), "\n";
unless (grep {/^$caldav_objectclass$/} @objectClasses) {
print "Adding objectClass ", $caldav_objectclass,"\n";
$entry->add('objectClass' => $caldav_objectclass);
$modified = 1;
}
}
# Add Freebusy URL if not present
my $fburl_attr = $config->val('ldap', 'fburl_attr');
if ($entry->get_value($fburl_attr)) {
print "Freebusy URL already defined (",$entry->get_value($fburl_attr),")\n";
}
else {
my $fburl = $config->val('sogo', 'url') . "/SOGo/dav/$username/freebusy.ifb";
print "Adding attribute ", $fburl_attr, " with value ", $fburl, "\n";
$entry->add($fburl_attr => $fburl);
$modified = 1;
}
if ($modified) {
# Perform update
my $msg = $entry->update($ldap);
if ($msg->is_error()) {
print "ERROR: Can't update entry: \n";
print $entry->dump();
print $msg->error(),"\n";
}
}
}
}
##
# Main
foreach my $username (@ARGV) {
#print $username,"\n";
&info($username) if $info;
&delete($username) if $delete;
&fburl($username) if $fburl;
}
$dbh->disconnect if $dbh;
$ldap->unbind if $ldap;