Subversion Repositories general

Compare Revisions

No changes between revisions

Ignore whitespace Rev 1221 → Rev 1220

/hostadmiral/trunk/backend/move_domain.sh
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/hostadmiral/trunk/backend/scripts.conf.sample
File deleted
/hostadmiral/trunk/backend/backend.pl
1,11 → 1,9
#!/usr/bin/perl -w
 
###################################################################################################
# #
# Sample backend for HostAdmiral #
# (copyleft) Anatoli Klassen #
# #
###################################################################################################
#
# Sample backend for HostAdmiral
# (copyleft) Anatoli Klassen
#
 
#
# Design:
33,6 → 31,8
 
# FIXME secure to show wrong (m.b. hacked) strings in logs and socket answers?
# FIXME double check validate_* functions
# FIXME by delete and rename domain - should the frontend send us an event for each mailbox
# (alias, destination etc) in the domain or should we do it at once?
 
use strict;
use vars;
42,7 → 42,7
use Time::HiRes qw( gettimeofday tv_interval );
use File::Basename qw( dirname );
 
#=== configuration ================================================================================
# == configuration =============================
 
my $base_dir = dirname($0);
 
58,7 → 58,7
my $config_name = "$base_dir/backend.conf";
require $config_name; # read the config
 
#=== constants ====================================================================================
# == constants =================================
 
# protocol description
my $protocol_ver_maj = '1';
96,7 → 96,7
my $code_script_error = 506;
my $code_panic = 600;
 
#=== internal global variables ====================================================================
# == internal global variables =================
 
my %handlers;
my $database_connection;
103,7 → 103,7
my $database_in_use = 0;
my $database_in_transaction = 0;
 
#=== functions ====================================================================================
# == functions =================================
 
sub handle_request
{
186,7 → 186,7
# rollback transaction if it's still open
if($database_in_transaction) {
eval {
log_error("Rollback transaction");
log_warn("Rollback transaction");
db_rollback_transaction();
};
if($@) {
202,10 → 202,8
}
}
 
### request handlers ##############################################################################
### request handlers ######################################
 
#-- user handlers ---------------------------------------------------------------------------------
 
sub handle_user_create
{
my $request = shift @_;
227,8 → 225,6
set_request_code($request, $code_ignored, "Not interesting in users");
}
 
#-- system user handlers --------------------------------------------------------------------------
 
sub handle_system_user_create
{
my $request = shift @_;
250,8 → 246,6
set_request_code($request, $code_ignored, "Not interesting in system users");
}
 
#-- domain handlers -------------------------------------------------------------------------------
 
sub save_domain
{
my $request = shift @_;
263,60 → 257,16
{ domain => $oldName },
{ domain => $name, comment => $comment, transport => 'virtual:' } );
# FIXME: transport => 'procmail:'? then restart mail system by transport change too
return 'error' if($res_action eq 'error');
# update users and aliases tables
if($name ne $oldName) {
my $dbh = db_begin($request);
return 'error' unless($dbh);
 
eval {
$dbh->do("update users set domain=?, login=concat(name,'\@',?),"
. " maildir=concat(?,'/',name,'/'), mailid=concat(id,'\@',?)"
. " where domain=?",
undef, $name, $name, $name, $name, $oldName);
};
if($@) {
return 'error' unless(db_end($request));
set_request_code($request, $code_db_inconsistent, "Cannot update users");
return 'error';
}
 
eval {
$dbh->do("update aliases set domain=?, alias=concat(name,'\@',?) where domain=?",
undef, $name, $name, $oldName);
};
if($@) {
return 'error' unless(db_end($request));
set_request_code($request, $code_db_inconsistent, "Cannot update aliases");
return 'error';
}
 
eval {
$dbh->do("update aliases set rcpt_domain=?, rcpt=concat(rcpt_name,'\@',?)"
. " where rcpt_domain=?",
undef, $name, $name, $oldName);
};
if($@) {
return 'error' unless(db_end($request));
set_request_code($request, $code_db_inconsistent, "Cannot update aliases");
return 'error';
}
 
return 'error' unless(db_end($request));
}
 
# restart postfix
if($res_action eq 'insert' || ($res_action eq 'update' && $name ne $oldName)) {
return 'error' unless(restart_mail_system());
}
# move domain dir
if($oldName ne $name) {
my $call_res = call_external_script($request, 'move_domain.sh', [ $oldName, $name ]);
log_debug("move_domain.sh: $call_res");
my $call_res = call_external_script($request, 'delete_domain.sh', [ $oldName ]);
log_debug("delete_domain.sh: $call_res");
if($call_res >= 3) {
set_request_code($request, $code_script_error, "Cannot move domain dir");
set_request_code($request, $code_script_error, "Cannot delete domain dir");
return 'error';
}
}
425,8 → 375,6
db_commit_transaction($request);
}
 
#-- mailbox handlers ------------------------------------------------------------------------------
 
sub update_mailbox_mailid
{
my $request = shift @_;
443,14 → 391,9
 
# create alias loop
my $res_action3 = save_to_db($request, 'aliases',
{ alias => "$id\@$domain", rcpt => "$id\@$domain" },
{ name => $id,
domain => $domain,
alias => "$id\@$domain",
rcpt_name => $id,
rcpt_domain => $domain,
rcpt => "$id\@$domain",
comment => "loop for $login\@$domain" } );
{ alias => "$id\@$domain", rcpt => "$id\@$domain" },
{ alias => "$id\@$domain", rcpt => "$id\@$domain",
comment => "loop for $login\@$domain" } );
return 0 if($res_action3 eq 'error');
 
return 1;
472,9 → 415,7
my $id;
my $res_action = save_to_db($request, 'users',
{ login => "$oldLogin\@$oldDomain" },
{ name => $login,
domain => $domain,
login => "$login\@$domain",
{ login => "$login\@$domain",
password => $password,
maildir => "$domain/$login/",
expired => $expired,
485,53 → 426,6
# set mailid for the new record
return 'error' unless(update_mailbox_mailid($request, $id, $login, $domain));
 
# update aliases table
if($domain ne $oldDomain || $login ne $oldLogin) {
my $dbh = db_begin($request);
return 'error' unless($dbh);
 
# find id
eval {
my $select_sth = $dbh->prepare("select id from users where login=?");
$select_sth->execute("$login\@$domain");
$id = $select_sth->fetchrow_array();
};
if(!$id || $@) {
return 'error' unless(db_end($request));
set_request_code($request, $code_db_inconsistent, "Cannot find id");
return;
}
 
# aliases
if($domain ne $oldDomain) {
eval {
$dbh->do("update aliases set rcpt_domain=?, rcpt=concat(rcpt_name,'\@',?)"
. " where rcpt_name=? and rcpt_domain=?",
undef, $domain, $domain, $id, $oldDomain);
};
if($@) {
return 'error' unless(db_end($request));
set_request_code($request, $code_db_inconsistent, "Cannot update aliases");
return 'error';
}
}
 
# the loop
eval {
$dbh->do("update aliases set domain=?, alias=?, rcpt_domain=?, rcpt=?, comment=?"
. " where alias=?",
undef, $domain, "$id\@$domain", $domain, "$id\@$domain",
"loop for $login\@$domain", "$id\@$oldDomain");
};
if($@) {
return 'error' unless(db_end($request));
set_request_code($request, $code_db_inconsistent, "Cannot update loop");
return 'error';
}
 
return 'error' unless(db_end($request));
}
 
# update disk
my $call_res = call_external_script($request, 'move_mailbox.sh',
[ (defined($systemUser) ? $systemUser : ''), "$oldDomain/$oldLogin", "$domain/$login" ]);
659,7 → 553,7
{ login => "$params{'login'}\@$params{'domain'}" } );
return if($res_action eq 'error');
 
my $res_action2 = delete_from_db($request, 'aliases', { rcpt => $mail_id } );
my $res_action2 = delete_from_db($request, 'aliases', { alias => $mail_id } );
return if($res_action2 eq 'error');
 
# delete from disk - last one, because disk has no transactions
683,8 → 577,6
db_commit_transaction($request);
}
 
#-- mail aliases handlers -------------------------------------------------------------------------
 
sub save_mail_alias_dest
{
my $request = shift @_;
727,16 → 619,9
# save
foreach my $rcpt (@$rcpts) {
log_debug("save $rcpt");
my ($rcpt_name, $rcpt_domain) = ($rcpt =~ /^(.*)\@(.*)$/);
my $res_action = save_to_db($request, 'aliases',
undef,
{ name => $address,
domain => $domain,
alias => "$address\@$domain",
rcpt_name => $rcpt_name,
rcpt_domain => $rcpt_domain,
rcpt => $rcpt,
comment => $comment } );
{ alias => "$address\@$domain", rcpt => $rcpt, comment => $comment } );
return 0 if($res_action eq 'error');
}
 
874,7 → 759,7
db_commit_transaction($request);
}
 
### validators ####################################################################################
### validators ############################################
 
sub validate_boolean
{
928,7 → 813,7
return ($_ eq '' || $_ >= 1000) ? 1 : 0; # additional security check
}
 
### request parsing ###############################################################################
### request parsing #######################################
 
sub decode_param
{
997,7 → 882,7
return %values;
}
 
### hanlders help functions #######################################################################
### hanlders help functions ###############################
 
sub restart_mail_system
{
1031,8 → 916,7
return 7;
}
elsif($res & 127) {
set_request_code($request, $code_exec_error,
"Script died with signal " . ($res & 127));
set_request_code($request, $code_exec_error, "Script died with signal " . ($res & 127));
return 7;
}
else {
1040,7 → 924,7
}
}
 
### db functions ##################################################################################
### db functions ##########################################
 
sub db_connect
{
1319,7 → 1203,7
return $res_action;
}
 
### logging and response formers ##################################################################
### logging and response formers ##########################
 
sub strip_request_password
{
1391,7 → 1275,7
print shift @_, ":\t", shift @_, "\n";
}
 
### main functions ################################################################################
### main functions ########################################
 
sub init
{
/hostadmiral/trunk/backend/delete_domain.sh
17,7 → 17,7
 
### config ################################################
 
. `dirname $0`/scripts.conf
ROOT=/var/spool/mail
 
### validate params #######################################
 
/hostadmiral/trunk/backend/move_mailbox.sh
25,7 → 25,8
 
### config ################################################
 
. `dirname $0`/scripts.conf
ROOT=/var/spool/mail
DEFAULT_OWNER=202
 
### validate params #######################################
 
/hostadmiral/trunk/backend/restart_mail_system.sh
15,10 → 15,6
# 5 - error from system
#
 
### config ################################################
 
. `dirname $0`/scripts.conf
 
### work ##################################################
 
/usr/local/sbin/postfix reload
/hostadmiral/trunk/backend/delete_mailbox.sh
18,7 → 18,7
 
### config ################################################
 
. `dirname $0`/scripts.conf
ROOT=/var/spool/mail
 
### validate params #######################################
 
/hostadmiral/trunk/backend
Property changes:
Modified: svn:ignore
backend.conf
-scripts.conf
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailAliasManager.java
18,8 → 18,7
UserBeforeDeleteListener,
UserDeletingListener,
InetDomainBeforeDeleteListener,
InetDomainDeletingListener,
MailboxDeletingListener
InetDomainDeletingListener
{
private MailAliasStore store;
 
34,11 → 33,6
throws ModelException
{
UserManager.getInstance().addBeforeDeleteListener(this);
UserManager.getInstance().addDeletingListener(this);
InetDomainManager.getInstance().addBeforeDeleteListener(this);
InetDomainManager.getInstance().addDeletingListener(this);
// FIXME register for mailbox before delete event? or silently delete destinations?
MailboxManager.getInstance().addDeletingListener(this);
}
 
public MailAlias create(User editor)
91,8 → 85,6
public void save(User editor, MailAlias mailAlias)
throws ModelException
{
// FIXME: how the onwer can save new destinations if he has no right to save the alias?
 
// security check
if(!mailAlias.editableBy(editor))
throw new ModelSecurityException();
317,28 → 309,6
return cascade;
}
 
public void mailboxDeleting(User editor, Mailbox mailbox)
throws ModelException
{
Collection mailAliases = store.listMailAliasesForMailbox(mailbox);
 
for(Iterator i = mailAliases.iterator(); i.hasNext(); ) {
MailAlias mailAlias = (MailAlias)i.next();
System.out.println("mailboxDeleting: " + mailAlias);
 
// FIXME is it possible that editor has right to delete mailbox
// but has no right to change alias?
if(mailAlias.mayChangeDestinations(editor)) {
for(Iterator j = mailAlias.getDestinations(editor).iterator(); j.hasNext(); ) {
MailAliasDestination dest = (MailAliasDestination)j.next();
if(mailbox == dest.getMailbox()) j.remove();
}
 
save(editor, mailAlias);
}
}
}
 
public static final Integer SORT_ADDRESS = new Integer(1);
public static final Integer SORT_DOMAIN = new Integer(2);
 
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailboxManager.java
36,11 → 36,8
throws ModelException
{
UserManager.getInstance().addBeforeDeleteListener(this);
UserManager.getInstance().addDeletingListener(this);
SystemUserManager.getInstance().addBeforeDeleteListener(this);
SystemUserManager.getInstance().addDeletingListener(this);
InetDomainManager.getInstance().addBeforeDeleteListener(this);
InetDomainManager.getInstance().addDeletingListener(this);
}
 
public Mailbox create(User editor)
306,7 → 303,6
Collection mailboxes = store.listMailboxesForSystemUser(user);
 
for(Iterator i = mailboxes.iterator(); i.hasNext(); ) {
// FIXME do not delete, just reset system user (?)
delete(editor, (Mailbox)i.next());
}
}
/hostadmiral/trunk/src/ak/hostadmiral/core/model/SystemUserManager.java
31,7 → 31,6
throws ModelException
{
UserManager.getInstance().addBeforeDeleteListener(this);
UserManager.getInstance().addDeletingListener(this);
}
 
public SystemUser create(User editor)
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailAliasDestination.java
135,7 → 135,7
+ (alias == null ? "_none_" : alias.getAddress() + "@"
+ (alias.getDomain() == null ? "_none_" : alias.getDomain().getName()))
+ "] mailbox=[" + (mailbox == null ? "_none_" : mailbox.getLogin() + "@"
+ (mailbox.getDomain() == null ? "_none_" : mailbox.getDomain().getName()))
+ (mailbox.getDomain() == null ? "_none_" : mailbox.getDomain().getName())) + "]"
+ "] email=[" + (email == null ? "_none_" : email) + "]";
}
}
/hostadmiral/trunk/src/ak/hostadmiral/core/model/store/hibernate/MailAliasHibernate.java
14,7 → 14,6
import ak.hostadmiral.util.hibernate.HibernateUtil;
import ak.hostadmiral.core.model.User;
import ak.hostadmiral.core.model.InetDomain;
import ak.hostadmiral.core.model.Mailbox;
import ak.hostadmiral.core.model.MailAlias;
import ak.hostadmiral.core.model.MailAliasManager;
import ak.hostadmiral.core.model.store.MailAliasStore;
210,7 → 209,7
{
throw new ModelStoreException(ex);
}
}
}
 
public Collection listMailAliasesForDomain(InetDomain domain)
throws ModelStoreException
224,23 → 223,8
{
throw new ModelStoreException(ex);
}
}
}
 
public Collection listMailAliasesForMailbox(Mailbox mailbox)
throws ModelStoreException
{
try {
return HibernateUtil.currentSession().find(
"select a from MailAlias a left join fetch a.owner"
+ " left join fetch a.destinations as dest where dest.mailbox = ?",
mailbox, Hibernate.entity(Mailbox.class) );
}
catch(HibernateException ex)
{
throw new ModelStoreException(ex);
}
}
 
protected static Map sortKeys = new HashMap();
protected static Map sortKeysSql = new HashMap();
private static boolean sortKeysInitialized = false;
/hostadmiral/trunk/src/ak/hostadmiral/core/model/store/MailAliasStore.java
5,7 → 5,6
import ak.hostadmiral.util.ModelStoreException;
import ak.hostadmiral.core.model.User;
import ak.hostadmiral.core.model.InetDomain;
import ak.hostadmiral.core.model.Mailbox;
import ak.hostadmiral.core.model.MailAlias;
 
public interface MailAliasStore
41,7 → 40,4
 
public Collection listMailAliasesForDomain(InetDomain domain)
throws ModelStoreException;
 
public Collection listMailAliasesForMailbox(Mailbox mailbox)
throws ModelStoreException;
}