App-CamelPKI
view release on metacpan or search on metacpan
lib/App/CamelPKI/CADB.pm view on Meta::CPAN
=head2 commit()
Commits all modifications made with L</add>, L</revoke> and
L</next_serial> since the construction of this object, or the previous
call to I<commit()>, whichever is latest. B<If commit() is not
called, no write will be made to the file system, and all
modifications will be lost!>.
=cut
sub commit {
my ($self) = @_;
$self->{dbix}->txn_commit();
$self->{dbix}->txn_begin();
}
=head2 max_serial($seqname)
Returns (an approximation of) the current status of the sequence named
$seqname, ie an integer which is guaranteed to be superior or equal to
all previous values previously returned by L</next_serial>, and
strictly inferior to all values that will be returned in the future.
=cut
sub max_serial {
my ($self, $seqname) = @_;
my $row = $self->{dbix}->resultset("Sequence")->find_or_new
({name => $seqname});
return ($row->in_storage ? $row->val : 0);
}
=head2 facet_readonly()
Returns a read-only copy of the database object: only L</search> and
L</max_serial> methods are available.
=cut
sub facet_readonly {
my ($self) = @_;
return bless { delegate => $self },
"App::CamelPKI::CADB::FacetReadOnly";
package App::CamelPKI::CADB::FacetReadOnly;
use Class::Facet from => "App::CamelPKI::CADB",
on_error => \&App::CamelPKI::Error::Privilege::on_facet_error,
delegate => [qw(search max_serial)];
}
=head2 debug_statements($debugsub)
This restricted method (see L<App::CamelPKI::RestrictedClassMethod>)
installs $debugsub as the SQL request observer on all
I<App::CamelPKI::CADB> objects constructed later. This method will be
called thusly for each SQL request:
$debugsub->($sql, @bind_values);
This mecanism is only destined for testing purposes; it should not
be used in production.
=cut
sub debug_statements : Restricted {
my ($class, $debugsub) = @_;
our $debugsub = $debugsub;
}
=head1 App::CamelPKI::CADB::Cursor
This class models a read only SQL cursor equivalent; instancies may be
constructed using L</search>.
An attentive reader will probably understand that's a fairly trivial
derivation of the L<DBIx::Class> API; However there is no reason to
return directly an instance of I<DBIx::Class> in L</search> because
it will violate the encapsulation of I<App::CamelPKI::CADB>. Consequence
could be a induced coupling (it should be impossible to refactor the
scheme without breaking the whole calling code), and worse, a
privilege escape leading to a security breach (because it's also
possible to write with a I<DBIx::Class> cursor).
=cut
package App::CamelPKI::CADB::Cursor;
=begin internals
=head2 _new($realcursor, $infos_resultset)
Constructor. $realcursor is an instance of
L<DBIx::Class::ResultSet> coming from
L</App::CamelPKI::CADB::_Schema::Certificate> which represents all certificates
to be enumerated; $infos_resultset is an instance of
L<DBIx::Class::ResultSet> coming from L</App::CamelPKI::CADB::_Schema::CertInfos>
which represents the B<totality> of B<CertInfos> in database, and it's the
job of I<App::CamelPKI::CADB::Cursor> to restrict this search to what it is
interresting.
=cut
sub _new {
my ($class, $cursor, $infos_resultset) = @_;
return bless {
index => 0,
cursor => $cursor,
infos_set => $infos_resultset,
}, $class;
}
=head2 _fetch_certificates()
Execute the SQL request that rocks, grab in one shot all certificates
and their revocation informations, and cache them in $self->{certs}
which become a list of objects form the
L</App::CamelPKI::CADB::_Schema::Certificate>.
lib/App/CamelPKI/CADB.pm view on Meta::CPAN
$schema = Bogus::Schema->connect($testdsn);
is($schema->resultset('Beware')->first->blob, $bogon,
"bogon has persisted as planned");
my $resultset = $schema->resultset('Beware')
->search({blob => $bogon});
is($resultset->count, 1, "searching per blob 1/2");
$resultset = $schema->resultset('Beware')
->search({blob => $bogon . "\0"});
is($resultset->count, 0, "searching per blob 2/2");
};
my $cert = App::CamelPKI::Certificate->parse
($test_self_signed_certs{"rsa1024"});
=head2 change_db_dir()
Change the value of $testdir and recreates an empty database therein.
=cut
my $testdir;
{
my $unique = 0;
sub change_db_dir {
$unique++;
$testdir = catdir(My::Tests::Below->tempdir, "testdb$unique");
}
}
change_db_dir();
test "initialisation of the DB" => sub {
local $SIG{__WARN__} = sub {
my $warn = shift;
if ($warn !~ /closing dbh with active statement handles/){
warn shift; fail
}
}; # Making warnings
# fatal, such as the usual suspect "Issuing rollback() ..."
my $db = App::CamelPKI::CADB->load($testdir);
ok($db->isa("App::CamelPKI::CADB"));
is($db->search()->count(), 0);
};
=head2 open_db()
Open a connection to the database for testing purposes. SQL requests
are recorded in the @queries global variable, so that tests are able
to inspect the requests they caused to be made. If the $debug_queries
variable is set to a true value, SQL requests will also be printed to
STDERR.
=cut
our @queries;
our $debug_queries;
App::CamelPKI::CADB->debug_statements(sub {
my ($sql, @bind_values) = @_;
push(@queries, $sql);
map { $_ = "<der>" if m/[\000-\010]/ } @bind_values;
diag join(" / ", $sql, @bind_values) . "\n" if $debug_queries;
});
sub open_db {
my $cadb = load App::CamelPKI::CADB($testdir);
return $cadb;
}
test "->add()" => sub {
my $cadb = open_db;
$cadb->add($cert, template => "foobar");
try {
$cadb->add($cert, zoinx => ["deux", "mille" ]);
fail("inserting doubled bloom prohibited");
} catch App::CamelPKI::Error::Database with {
pass;
};
$cadb = open_db;
$cadb->add($cert, template => "foobar"); # Works because the
# transaction has been rollbacked
$cadb->add(App::CamelPKI::Certificate->parse
($test_entity_certs{"rsa1024"}),
foo => "bar",
zoinx => ["is", "tan" ],
);
$cadb->commit;
is($cadb->search()->count(), 2, "certificates in base");
};
test "->search() in list context" => sub {
my $cadb = open_db;
my @certs = $cadb->search(-initially_valid_at => "20010101020400Z");
is(scalar(@certs), 0);
@certs = $cadb->search(-initially_valid_at => "now");
is(scalar(@certs), 2, "all certificates");
grep { ok($_->isa("App::CamelPKI::Certificate")) } @certs;
@certs = $cadb->search(-certificate => $cert);
is(scalar(@certs), 1);
ok($certs[0]->equals($cert));
};
test "->search() with a cursor" => sub {
my $cadb = open_db;
my $cursor = $cadb->search(-revoked => undef);
is($cursor->count, 2);
ok($cursor->has_more);
ok($cursor->certificate->isa("App::CamelPKI::Certificate"));
$cursor->next;
ok($cursor->has_more);
ok($cursor->certificate->isa("App::CamelPKI::Certificate"));
$cursor->next;
ok(! $cursor->has_more);
$cursor = $cadb->search(-revoked => undef);
isnt($cursor->infos, undef,
"consulting ->infos available "
. "even if we don't look for them");
$cursor = $cadb->search(template => "foobar", -revoked => 0);
( run in 0.689 second using v1.01-cache-2.11-cpan-2398b32b56e )