aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Fripost/Schema/Domain.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Fripost/Schema/Domain.pm')
-rw-r--r--lib/Fripost/Schema/Domain.pm58
1 files changed, 36 insertions, 22 deletions
diff --git a/lib/Fripost/Schema/Domain.pm b/lib/Fripost/Schema/Domain.pm
index 3caffb5..4cc12e4 100644
--- a/lib/Fripost/Schema/Domain.pm
+++ b/lib/Fripost/Schema/Domain.pm
@@ -18,11 +18,12 @@ use utf8;
use parent 'Fripost::Schema';
use Fripost::Schema::Util qw/softdie dn2mail email_valid domain_valid
- canonical_dn ldap_explode_dn ldap_error/;
+ canonical_dn ldap_explode_dn ldap_error
+ ldap_assert_absent/;
use Fripost::Schema::Mail;
use Net::IDN::Encode qw/domain_to_ascii domain_to_unicode email_to_unicode/;
use URI::Escape::XS 'encodeURIComponent';
-use Encode;
+use Encode ();
use Net::Domain::TLD 'tld_exists';
use Net::DNS::Dig;
use Net::Whois::Parser 'parse_whois';
@@ -280,7 +281,7 @@ sub _entries_to_domains {
if not @$keys or grep { $_ eq 'description' } @$keys;
}
else {
- die "Missing translation for domain attribute ‘".$attr."’.";
+ die "Missing translation for domain attribute ‘".$attr."’";
}
}
@@ -327,7 +328,7 @@ sub _keys_to_attrs {
);
my %attrs;
foreach my $k (@_) {
- die "Missing translation for key ‘".$k."’."
+ die "Missing translation for key ‘".$k."’"
unless exists $map{$k};
if (ref $map{$k} eq 'ARRAY') {
$attrs{$_} = 1 for @{$map{$k}};
@@ -410,7 +411,7 @@ sub list_owner_emails {
my $domain;
until ( tld_exists($tld) ) {
- softdie ("‘".$domainname."’ has an Invalid TLD.", %options) // return
+ softdie ("‘".$domainname."’ has an Invalid TLD", %options) // return
unless $tld =~ /\./;
$domain = $tld;
@@ -495,25 +496,33 @@ sub add {
my $domainname = $domain->{name};
# Check domain validity.
- &_is_valid($domain, %options) // return;
- my $dn = $self->mail2dn( $domain->{name} );
-
- # Search for an existing domain with the same name.
- my $count = $self->search($domain->{name}, %options, '-count' => 1);
- softdie ( "Domain ‘".$domainname."’ already exists.", %options ) // return
- if not $options{'-append'} and $count;
- # Stop here in dry-run mode.
- return 1 if $options{'-dry-run'};
+ &_assert_valid($domain, %options) // return;
+
+ my $exists;
+ if ($options{'-dry-run'} or $options{'-append'}) {
+ # Search for an existing domain with the same name. We can't
+ # use our previously defined method here, since the current user
+ # may not have read access to the entry. There is a race
+ # condition since someone could modify the directory between
+ # this check and the actual insertion, but then the insertion
+ # would fail.
+ $exists = ldap_assert_absent( $self, $domain->{name}, undef, %options)
+ // return;
+ return 1 if $options{'-dry-run'};
+ }
# Convert the domain into a LDAP entry, and remove keys to empty values.
my %attrs = $self->_domain_to_entry (%$domain);
- Fripost::Schema::Util::clean_ldap_entry( \%attrs );
+ Fripost::Schema::Util::ldap_clean_entry( \%attrs );
my ($mesg, $token);
- if ($options{'-append'} and $count) {
+ my $dn = $self->mail2dn( $domain->{name} );
+ if ($options{'-append'} and $exists) {
# Replace single valued attributes; Add other attributes.
- my %unique = ( fripostIsStatusActive => $attrs{fripostIsStatusActive} );
- delete $attrs{$_} for (keys %unique);
+ my %unique;
+ foreach (qw/fripostIsStatusActive/) {
+ $unique{$_} = delete $attrs{$_} if exists $attrs{$_};
+ }
$mesg = $self->ldap->modify( $dn, replace => \%unique, add => \%attrs );
}
else {
@@ -528,6 +537,10 @@ sub add {
}
# The default owner is the current user.
$attrs{fripostOwner} //= [ $self->whoami ];
+ $options{'-die'} = { Net::LDAP::Constant::LDAP_ALREADY_EXISTS =>
+ "‘".$domainname."’ exists"
+ , Net::LDAP::Constant::LDAP_SUCCESS => 0 }
+ unless exists $options{'-die'};
$mesg = $self->ldap->add( $dn, attrs => [ %attrs ] );
}
@@ -594,7 +607,7 @@ sub _domain_to_entry {
[ map { $self->mail2dn($_) } @{$domain{postmaster}} ];
}
else {
- die "Missing translation for domain key ‘".$key."’.";
+ die "Missing translation for domain key ‘".$key."’";
}
}
return %entry;
@@ -681,7 +694,7 @@ sub replace {
return if $options{'-error'} && ${$options{'-error'}};
# Check domain validity.
- &_is_valid($domain, %options) // return;
+ &_assert_valid($domain, %options, -replace => 1) // return;
return 1 if $options{'-dry-run'};
my %entry = $self->_domain_to_entry (%$domain);
@@ -693,11 +706,12 @@ sub replace {
# Ensure that the given domain is valid.
-sub _is_valid {
+sub _assert_valid {
my $d = shift;
my %options = @_;
eval {
- Fripost::Schema::Util::must_attrs( $d, qw/name isActive/ );
+ Fripost::Schema::Util::must_attrs( $d, qw/name isActive/ )
+ unless $options{'-append'} or $options{'-replace'};
$d->{name} = domain_valid( domain_to_ascii ($d->{name}) );
$d->{catchAll} = [ map { email_valid($_, -prefix => 'fake') }
@{$d->{catchAll}} ]