view release on metacpan or search on metacpan
config/sql/component_Config.pm view on Meta::CPAN
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# *************************************************************************
#
# sql/component_Config.pm
#
# SQL statements related to components
#
set( 'SQL_COMPONENT_SELECT_ALL', q/
SELECT cid, path, source, acl, validations
FROM components
/ );
#
set( 'SQL_COMPONENT_SELECT_ALL_NO_SOURCE', q/
SELECT cid, path, acl, validations
FROM components
/ );
#
set( 'SQL_COMPONENT_SELECT_BY_CID', q/
SELECT cid, path, source, acl, validations
FROM components WHERE cid = ?
/ );
#
set( 'SQL_COMPONENT_SELECT_BY_PATH', q/
SELECT cid, path, source, acl, validations
FROM components WHERE path = ?
/ );
#
set( 'SQL_COMPONENT_INSERT', q/
INSERT INTO components
(path, source, acl, validations)
VALUES (?, ?, ?, ?)
RETURNING cid, path, source, acl, validations
/ );
set( 'SQL_COMPONENT_UPDATE', q/
UPDATE components
SET path = ?, source = ?, acl = ?, validations = ?
WHERE cid = ?
RETURNING cid, path, source, acl, validations
/ );
set( 'SQL_COMPONENT_DELETE', q/
DELETE FROM components
WHERE cid = ?
RETURNING cid, path, source, acl, validations
/ );
# -----------------------------------
# DO NOT EDIT ANYTHING BELOW THIS LINE
# -----------------------------------
use strict;
use warnings;
1;
config/sql/dbinit_Config.pm view on Meta::CPAN
q/CREATE TRIGGER code_to_upper BEFORE INSERT OR UPDATE ON activities
FOR EACH ROW EXECUTE PROCEDURE code_to_upper()/,
q/CREATE TRIGGER disabled_to_zero BEFORE INSERT OR UPDATE ON activities
FOR EACH ROW EXECUTE PROCEDURE disabled_to_zero()/,
# the 'components' table
q#-- components
CREATE TABLE components (
cid serial PRIMARY KEY,
path varchar(2048) UNIQUE NOT NULL,
source text NOT NULL,
acl varchar(16) NOT NULL,
validations text,
CONSTRAINT kosher_path CHECK (path ~* '^[[:alnum:]_.][[:alnum:]_/.-]+$')
)#,
q/-- trigger function to make 'cid' field immutable
CREATE OR REPLACE FUNCTION cid_immutable() RETURNS trigger AS $IMM$
BEGIN
IF OLD.cid <> NEW.cid THEN
RAISE EXCEPTION 'components.cid field is immutable';
END IF;
RETURN NEW;
END;
$IMM$ LANGUAGE plpgsql/,
q/-- trigger the trigger
CREATE TRIGGER no_cid_update BEFORE UPDATE ON components
FOR EACH ROW EXECUTE PROCEDURE cid_immutable()/,
# the 'intervals' table
q/-- intervals
CREATE TABLE IF NOT EXISTS intervals (
iid serial PRIMARY KEY,
eid integer REFERENCES employees (eid) NOT NULL,
aid integer REFERENCES activities (aid) NOT NULL,
intvl tstzrange NOT NULL,
long_desc text,
lib/App/Dochazka/REST/Dispatch.pm view on Meta::CPAN
# first pass
return 1 if $pass == 1 ;
# second pass
return App::Dochazka::REST::Model::Component::get_all_components(
$self->context->{'dbix_conn'},
);
}
=head3 handler_post_component_cid
Handler for 'POST component/cid' resource.
=cut
sub handler_post_component_cid {
my ( $self, $pass ) = @_;
$log->debug( "Entering " . __PACKAGE__ . "::handler_post_component_cid" );
# first pass
return 1 if $pass == 1;
# second pass
# - check that entity is kosher
my $status = shared_entity_check( $self, 'cid' );
return $status unless $status->ok;
my $context = $self->context;
my $entity = $context->{'request_entity'};
# - get cid and look it up
my $cid = $entity->{'cid'};
my $comp = shared_first_pass_lookup( $self, 'CID', $cid );
return $fail unless $cid;
# - perform the update
return shared_update_component( $self, $comp, $entity );
}
=head3 handler_post_component_path
Handler for 'POST component/path' resource. This is a little more complicated
because it can be either create or modify.
lib/App/Dochazka/REST/Dispatch.pm view on Meta::CPAN
if ( $comp ) {
return shared_update_component( $self, $comp, $entity );
} else {
my $status = shared_entity_check( $self, 'path', 'source', 'acl' );
return $status unless $status->ok;
return shared_insert_component( $self, $path, $entity );
}
}
=head3 handler_component_cid
Handler for the 'component/cid/:cid' resource.
=cut
sub handler_component_cid {
my ( $self, $pass ) = @_;
$log->debug( "Entering " . __PACKAGE__ . "::handler_component_cid" );
my $context = $self->context;
# first pass
if ( $pass == 1 ) {
my $comp = shared_first_pass_lookup( $self, 'cid', $context->{'mapping'}->{'cid'} );
return 0 unless $comp;
$context->{'stashed_component_object'} = $comp;
return 1;
}
# second pass
if ( $context->{'method'} eq 'GET' ) {
return $CELL->status_ok( 'DISPATCH_COMPONENT_FOUND',
payload => $context->{'stashed_component_object'}
);
lib/App/Dochazka/REST/Docs/Resources.pm view on Meta::CPAN
=over
Allowed methods: GET
Retrieves all component objects in the database.
=back
=head2 C<< component/cid >>
=over
Allowed methods: POST
Enables existing component objects to be updated by sending a POST request to
the REST server. Along with the properties to be modified, the request body
must include an 'cid' property, the value of which specifies the cid to be
updated.
=back
=head2 C<< component/cid/:cid >>
=over
Allowed methods: DELETE, GET, PUT
This resource allows the user to GET, PUT, or DELETE an component object by its
cid.
=over
=item * GET
Retrieves an component object by its cid.
=item * PUT
Updates the component object whose cid is specified by the ':cid' URI parameter.
The fields to be updated and their new values should be sent in the request
body, e.g., like this:
{ "path" : "new/path", "source" : "new source", "acl" : "inactive" }
=item * DELETE
Deletes the component object whose cid is specified by the ':cid' URI parameter.
This will work only if nothing in the database refers to this component.
=back
=back
=head2 C<< component/path >>
lib/App/Dochazka/REST/Model/Component.pm view on Meta::CPAN
...
=head1 DATA MODEL
=head2 Components in the database
CREATE TABLE components (
cid serial PRIMARY KEY,
path varchar(2048) UNIQUE NOT NULL,
source text NOT NULL,
acl varchar(16) NOT NULL,
validations textj
)
=head2 Components in the Perl API
=over
=item * constructor (L<spawn>)
=item * basic accessors (L<cid>, L<path>, L<source>, L<acl>, L<validations>)
=item * L<reset> (recycles an existing object by setting it to desired state)
=item * L<TO_JSON> (returns 'unblessed' version of an Activity object)
=item * L<compare> (compare two objects)
=item * L<clone> (clone an object)
=item * L<insert> (inserts object into database)
=item * L<update> (updates database to match the object)
=item * L<delete> (deletes record from database if nothing references it)
=item * L<load_by_cid> (loads a single activity into an object)
=item * L<load_by_path> (loads a single activity into an object)
=back
L<App::Dochazka::REST::Model::Component> also exports some convenience
functions:
=over
=item * L<cid_exists> (boolean function)
=item * L<path_exists> (boolean function)
=item * L<cid_by_path> (given a path, returns CID)
=item * L<get_all_components> (self-explanatory)
=back
For basic C<component> object workflow, see the unit tests in
C<t/model/component.t>.
=cut
use Exporter qw( import );
our @EXPORT_OK = qw( cid_exists path_exists cid_by_path get_all_components );
=head1 METHODS
=head2 insert
Instance method. Takes the object, as it is, and attempts to insert it into
lib/App/Dochazka/REST/Model/Component.pm view on Meta::CPAN
Returns status object.
=cut
sub update {
my $self = shift;
my ( $context ) = validate_pos( @_, { type => HASHREF } );
return $CELL->status_err( 'DOCHAZKA_MALFORMED_400' ) unless
(
$self->{'cid'} and
(
$self->{'path'} or $self->{'source'} or $self->{'acl'}
)
);
return $CELL->status_err( 'DOCHAZKA_MALFORMED_400' ) if
(
$self->{'acl'} and not scalar(
grep { $self->{'acl'} eq $_ } ( 'admin', 'active', 'inactive', 'passerby' )
)
);
my $status = cud(
conn => $context->{'dbix_conn'},
eid => $context->{'current'}->{'eid'},
object => $self,
sql => $site->SQL_COMPONENT_UPDATE,
attrs => [ 'path', 'source', 'acl', 'validations', 'cid' ],
);
$self->create_file if $status->ok;
return $status;
}
=head2 delete
lib/App/Dochazka/REST/Model/Component.pm view on Meta::CPAN
sub delete {
my $self = shift;
my ( $context ) = validate_pos( @_, { type => HASHREF } );
my $status = cud(
conn => $context->{'dbix_conn'},
eid => $context->{'current'}->{'eid'},
object => $self,
sql => $site->SQL_COMPONENT_DELETE,
attrs => [ 'cid' ],
);
if ( $status->ok ) {
$self->delete_file;
$self->reset( cid => $self->{cid} );
}
return $status;
}
=head2 load_by_cid
Loads component from database, by the CID provided in the argument list,
into a newly-spawned object. The CID must be an exact match. Returns a
status object: if the object is loaded, the status code will be
'DISPATCH_RECORDS_FOUND' and the object will be in the payload; if
the CID is not found in the database, the status code will be
'DISPATCH_NO_RECORDS_FOUND'. A non-OK status indicates a DBI error.
=cut
sub load_by_cid {
my $self = shift;
my ( $conn, $cid ) = validate_pos( @_,
{ isa => 'DBIx::Connector' },
{ type => SCALAR },
);
return load(
conn => $conn,
class => __PACKAGE__,
sql => $site->SQL_COMPONENT_SELECT_BY_CID,
keys => [ $cid ],
);
}
=head2 load_by_path
Analogous method to L<"load_by_cid">.
=cut
sub load_by_path {
my $self = shift;
my ( $conn, $path ) = validate_pos( @_,
{ isa => 'DBIx::Connector' },
{ type => SCALAR },
);
lib/App/Dochazka/REST/Model/Component.pm view on Meta::CPAN
return $interp->run($path, %ARGS)->output;
}
=head1 FUNCTIONS
The following functions are not object methods.
=head2 cid_exists
Boolean function
=head2 path_exists
Boolean function
=cut
BEGIN {
no strict 'refs';
*{'cid_exists'} = App::Dochazka::REST::Model::Shared::make_test_exists( 'cid' );
*{'path_exists'} = App::Dochazka::REST::Model::Shared::make_test_exists( 'path' );
}
=head2 cid_by_path
Given a path, attempt to retrieve the corresponding CID.
Returns CID or undef on failure.
=cut
sub cid_by_path {
my ( $conn, $path ) = validate_pos( @_,
{ isa => 'DBIx::Connector' },
{ type => SCALAR },
);
my $status = __PACKAGE__->load_by_path( $conn, $path );
return $status->payload->{'cid'} if $status->code eq 'DISPATCH_RECORDS_FOUND';
return;
}
=head2 get_all_components
Returns a reference to a hash of hashes, where each hash is one component object.
=cut
lib/App/Dochazka/REST/ResourceDefs.pm view on Meta::CPAN
acl_profile => 'admin',
cli => 'component all',
description => 'Retrieve all component objects',
documentation => <<'EOH',
=pod
Retrieves all component objects in the database.
EOH
},
# /component/cid
'component/cid' =>
{
parent => 'component',
handler => {
POST => 'handler_post_component_cid',
},
acl_profile => 'admin',
cli => 'component cid',
description => 'Update an existing component object via POST request (cid must be included in request body)',
documentation => <<'EOH',
=pod
Enables existing component objects to be updated by sending a POST request to
the REST server. Along with the properties to be modified, the request body
must include an 'cid' property, the value of which specifies the cid to be
updated.
EOH
},
# /component/cid/:cid
'component/cid/:cid' =>
{
parent => 'component',
handler => {
GET => 'handler_component_cid',
PUT => 'handler_component_cid',
DELETE => 'handler_component_cid',
},
acl_profile => 'admin',
cli => 'component cid $cid',
validations => {
'cid' => 'Int',
},
description => 'GET, PUT, or DELETE an component object by its cid',
documentation => <<'EOH',
=pod
This resource allows the user to GET, PUT, or DELETE an component object by its
cid.
=over
=item * GET
Retrieves an component object by its cid.
=item * PUT
Updates the component object whose cid is specified by the ':cid' URI parameter.
The fields to be updated and their new values should be sent in the request
body, e.g., like this:
{ "path" : "new/path", "source" : "new source", "acl" : "inactive" }
=item * DELETE
Deletes the component object whose cid is specified by the ':cid' URI parameter.
This will work only if nothing in the database refers to this component.
=back
EOH
},
# /component/path
'component/path' =>
{
parent => 'component',
handler => {
POST => 'handler_post_component_path',
},
acl_profile => 'admin',
cli => 'component cid',
description => 'Update an existing component object via POST request (component path must be included in request body)',
documentation => <<'EOH',
=pod
This resource enables existing component objects to be updated, and new
component objects to be inserted, by sending a POST request to the REST server.
Along with the properties to be modified/inserted, the request body must
include an 'path' property, the value of which specifies the component to be
updated.
EOH
lib/App/Dochazka/REST/Shared.pm view on Meta::CPAN
my ( $status, $thing );
if ( uc($key) eq 'AID' ) {
$thing = 'activity';
$status = App::Dochazka::REST::Model::Activity->load_by_aid( $conn, $value );
} elsif ( $key eq 'code' ) {
$thing = 'activity';
$status = App::Dochazka::REST::Model::Activity->load_by_code( $conn, $value );
} elsif ( uc($key) eq 'CID' ) {
$thing = 'component';
$status = App::Dochazka::REST::Model::Component->load_by_cid( $conn, $value );
} elsif ( $key eq 'path' ) {
$thing = 'component';
$status = App::Dochazka::REST::Model::Component->load_by_path( $conn, $value );
} elsif ( uc($key) eq 'EID' ) {
$thing = 'employee';
$status = App::Dochazka::REST::Model::Employee->load_by_eid( $conn, $value );
} elsif ( $key eq 'nick' ) {
$thing = 'employee';
$status = App::Dochazka::REST::Model::Employee->load_by_nick( $conn, $value );
} elsif ( $key eq 'sec_id' ) {
lib/App/Dochazka/REST/Shared.pm view on Meta::CPAN
- $comp is a component object (blessed hashref)
- $over is a hashref with zero or more component properties and new values
The values from $over replace those in $comp
=cut
sub shared_update_component {
my ( $d_obj, $comp, $over ) = @_;
$log->debug("Entering " . __PACKAGE__ . "::shared_update_component" );
delete $over->{'cid'} if exists $over->{'cid'};
if ( pre_update_comparison( $comp, $over ) ) {
my $status = $comp->update( $d_obj->context );
return $status unless $status->level eq 'ERR' and $status->code eq 'DOCHAZKA_MALFORMED_400';
}
$d_obj->mrest_declare_status( code => 400, explanation => "DISPATCH_ILLEGAL_ENTITY" );
return $fail;
}
=head2 shared_update_history
lib/App/Dochazka/REST/Test.pm view on Meta::CPAN
}
=head2 delete_testing_component
Tests will need to set up and tear down testing components
=cut
sub delete_testing_component {
my $cid = shift;
my $status = App::Dochazka::REST::Model::Component->load_by_cid( $dbix_conn, $cid );
is( $status->level, 'OK', 'delete_testing_component 1' );
my $act = $status->payload;
$status = $act->delete( $faux_context );
is( $status->level, 'OK', 'delete_testing_component 2' );
return;
}
=head2 test_schedule_model
t/dispatch/component.t view on Meta::CPAN
note( '=============================' );
my $base = 'component/all';
docu_check($test, $base);
note( 'insert an component' );
my $foobar = create_testing_component(
path => 'FOOBAR',
source => 'source code of FOOBAR',
acl => 'passerby'
);
my $cid_of_foobar = $foobar->cid;
ok( path_exists_by_dispatch( "FOOBAR" ) );
ok( path_exists( $dbix_conn, "FOOBAR" ) );
ok( -o File::Spec->catfile( $comp_root, $foobar->path ) );
note( "GET on $base" );
req( $test, 403, 'demo', 'GET', $base );
my $status = req( $test, 200, 'root', 'GET', $base );
is( $status->level, 'OK', "GET $base 2" );
is( $status->code, 'DISPATCH_RECORDS_FOUND', "GET $base 3" );
ok( $status->{count} );
ok( exists $status->{payload}, "GET $base 5" );
ok( scalar @{ $status->payload } );
note( 'testing component is present' );
ok( scalar( grep { $_->{path} eq 'FOOBAR'; } @{ $status->payload } ), "GET $base 7" );
note( 'delete the testing component' );
delete_testing_component( $cid_of_foobar );
ok( ! path_exists_by_dispatch( "FOOBAR" ) );
ok( ! path_exists( $dbix_conn, "FOOBAR" ) );
note( "PUT, POST, DELETE on $base" );
foreach my $method ( 'PUT', 'POST', 'DELETE' ) {
foreach my $user ( 'demo', 'active', 'piggy', 'root' ) {
req( $test, 405, $user, $method, $base );
}
}
note( '========================' );
note( '"component/cid" resource' );
note( '========================' );
$base = 'component/cid';
docu_check($test, "$base");
note( "GET, PUT on $base" );
foreach my $method ( 'GET', 'PUT' ) {
foreach my $user ( 'demo', 'active', 'root', 'WOMBAT5', 'WAMBLE owdkmdf 5**' ) {
req( $test, 405, $user, $method, $base );
}
}
note( "POST on $base" );
my $foowop = create_testing_component( path => 'FOOWOP', source => 'nada', acl => 'passerby' );
my $cid_of_foowop = $foowop->cid;
my $full_path_of_foowop = File::Spec->catfile( $comp_root, $foowop->path );
ok( -o $full_path_of_foowop );
is( "nada", read_file( $full_path_of_foowop ) );
note( 'test if expected behavior behaves as expected (update)' );
my $component_obj = '{ "cid" : ' . $cid_of_foowop . ', "source" : "wop wop ng", "acl" : "inactive" }';
req( $test, 403, 'demo', 'POST', $base, $component_obj );
$status = req( $test, 200, 'root', 'POST', $base, $component_obj );
is( $status->level, 'OK', "POST $base 4" );
is( $status->code, 'DOCHAZKA_CUD_OK', "POST $base 5" );
ok( defined $status->payload );
is( $status->payload->{'acl'}, 'inactive', "POST $base 6" );
is( $status->payload->{'source'}, 'wop wop ng', "POST $base 7" );
ok( -o File::Spec->catfile( $comp_root, $status->payload->{path} ) );
is( $full_path_of_foowop, File::Spec->catfile( $comp_root, $status->payload->{path} ) );
is( "wop wop ng", read_file( $full_path_of_foowop ) );
note( 'non-existent cid and also out of range' );
$component_obj = '{ "cid" : 3434342342342, "source" : 3434341, "acl" : "passerby" }';
dbi_err( $test, 500, 'root', 'POST', $base, $component_obj, qr/out of range for type integer/ );
note( 'non-existent cid' );
$component_obj = '{ "cid" : 342342342, "source" : 3434341, "acl" : "passerby" }';
req( $test, 404, 'root', 'POST', $base, $component_obj );
note( 'throw a couple curve balls' );
my $weirded_object = '{ "copious_turds" : 555, "source" : "wang wang wazoo", "acl" : "passerby" }';
req( $test, 400, 'root', 'POST', $base, $weirded_object );
my $no_closing_bracket = '{ "copious_turds" : 555, "source" : "wang wang wazoo", "acl" : "passerby"';
req( $test, 400, 'root', 'POST', $base, $no_closing_bracket );
$weirded_object = '{ "cid" : "!!!!!", "source" : "down it goes" }';
dbi_err( $test, 500, 'root', 'POST', $base, $weirded_object, qr/invalid input syntax for type integer/ );
my $illegal_acl = '{ "cid" : ' . $cid_of_foowop . ', "path" : "library/machinations.mc", "source" : "wang wang wazoo", "acl" : "puppy" }';
req( $test, 400, 'root', 'POST', $base, $illegal_acl );
note( 'delete the testing component' );
ok( -e $full_path_of_foowop );
delete_testing_component( $cid_of_foowop );
ok( ! -e $full_path_of_foowop );
note( "DELETE on $base" );
req( $test, 405, 'demo', 'DELETE', $base );
req( $test, 405, 'root', 'DELETE', $base );
req( $test, 405, 'WOMBAT5', 'DELETE', $base );
note( '=============================' );
note( '"component/cid/:cid" resource' );
note( '=============================' );
$base = 'component/cid';
docu_check($test, "$base/:cid");
note( 'insert an component and disable it here' );
$foobar = create_testing_component( path => 'FOOBAR', source => 'wombat', acl => 'passerby' );
$cid_of_foobar = $foobar->cid;
my $full_path_of_foobar = File::Spec->catfile( $comp_root, $foobar->path );
ok( -o $full_path_of_foobar );
is( "wombat", read_file( $full_path_of_foobar ) );
note( "GET on $base/:cid" );
note( "fail as demo 403" );
req( $test, 403, 'demo', 'GET', "$base/$cid_of_foobar" );
note( "succeed as root cid_of_foobar" );
$status = req( $test, 200, 'root', 'GET', "$base/$cid_of_foobar" );
ok( $status->ok, "GET $base/:cid 2" );
is( $status->code, 'DISPATCH_COMPONENT_FOUND', "GET $base/:cid 3" );
is_deeply( $status->payload, {
cid => $cid_of_foobar,
path => 'FOOBAR',
source => 'wombat',
acl => 'passerby',
validations => undef,
}, "GET $base/:cid 4" );
note( "fail invalid (non-integer) cid" );
req( $test, 400, 'root', 'GET', "$base/jj" );
note( "fail non-existent cid" );
req( $test, 404, 'root', 'GET', "$base/444" );
note( "PUT on $base/:cid" );
$component_obj = '{ "path" : "FOOBAR", "source" : "The bar of foo", "acl" : "inactive" }';
# - test with demo fail 403
req( $test, 403, 'demo', 'PUT', "$base/$cid_of_foobar", $component_obj );
note( 'test with root (successful update)' );
$status = req( $test, 200, 'root', 'PUT', "$base/$cid_of_foobar", $component_obj );
is( $status->level, 'OK', "PUT $base/:cid 3" );
is( $status->code, 'DOCHAZKA_CUD_OK', "PUT $base/:cid 4" );
is( ref( $status->payload ), 'HASH', "PUT $base/:cid 5" );
is( $status->payload->{path}, 'FOOBAR' );
is( $status->payload->{source}, 'The bar of foo' );
is( $status->payload->{acl}, 'inactive' );
is( "The bar of foo", read_file( $full_path_of_foobar ) );
note( 'change ACL to active' );
$status = req( $test, 200, 'root', 'PUT', "$base/$cid_of_foobar", '{ "acl":"active" }' );
is( $status->level, 'OK' );
is( $status->code, 'DOCHAZKA_CUD_OK' );
is( ref( $status->payload ), 'HASH' );
is( $status->payload->{path}, 'FOOBAR' );
is( $status->payload->{source}, 'The bar of foo' );
is( $status->payload->{acl}, 'active' );
is( "The bar of foo", read_file( $full_path_of_foobar ) );
note( 'attempt ot change ACL to an illegal value' );
req( $test, 400, 'root', 'PUT', "$base/$cid_of_foobar", '{ "acl":"puppy" }' );
note( 'make an component object out of the payload' );
$foobar = App::Dochazka::REST::Model::Component->spawn( $status->payload );
is( $foobar->source, "The bar of foo", "PUT $base/:cid 5" );
is( $foobar->acl, "active", "PUT $base/:cid 6" );
note( 'test with root no request body' );
req( $test, 400, 'root', 'PUT', "$base/$cid_of_foobar" );
note( 'test with root fail invalid JSON' );
req( $test, 400, 'root', 'PUT', "$base/$cid_of_foobar", '{ asdf' );
note( 'test with root fail invalid cid' );
req( $test, 400, 'root', 'PUT', "$base/asdf", '{ "legal":"json" }' );
note( 'with valid JSON that is not what we are expecting' );
req( $test, 400, 'root', 'PUT', "$base/$cid_of_foobar", '0' );
note( 'with valid JSON that has some bogus properties' );
req( $test, 400, 'root', 'PUT', "$base/$cid_of_foobar", '{ "legal":"json" }' );
req( $test, 400, 'root', 'PUT', "$base/$cid_of_foobar", '{ "aid":"json" }' );
note( "POST on $base/:cid" );
req( $test, 405, 'demo', 'POST', "$base/$cid_of_foobar" );
req( $test, 405, 'root', 'POST', "$base/$cid_of_foobar" );
note( "DELETE on $base/:cid" );
note( 'demo fail 403' );
req( $test, 403, 'demo', 'DELETE', "$base/$cid_of_foobar" );
note( 'root success' );
note( "DELETE $base/$cid_of_foobar" );
ok( -e $full_path_of_foobar );
$status = req( $test, 200, 'root', 'DELETE', "$base/$cid_of_foobar" );
is( $status->level, 'OK', "DELETE $base/:cid 3" );
is( $status->code, 'DOCHAZKA_CUD_OK', "DELETE $base/:cid 4" );
note( 'really gone' );
req( $test, 404, 'root', 'GET', "$base/$cid_of_foobar" );
ok( ! -e $full_path_of_foobar );
note( 'root fail invalid cid' );
req( $test, 400, 'root', 'DELETE', "$base/asd" );
note( "=============================" );
note( "'component/path' resource" );
note( "=============================" );
$base = 'component/path';
docu_check($test, "$base");
note( "GET, PUT on $base" );
t/dispatch/component.t view on Meta::CPAN
}
note( "POST on $base" );
note( "insert: expected behavior" );
$component_obj = '{ "path" : "library/foowang.mc", "source" : "wang wang wazoo", "acl" : "passerby" }';
req( $test, 403, 'demo', 'POST', $base, $component_obj );
$status = req( $test, 200, 'root', 'POST', $base, $component_obj );
is( $status->level, 'OK', "POST $base 4" );
is( $status->code, 'DOCHAZKA_CUD_OK', "POST $base 5" );
my $cid_of_foowang = $status->payload->{'cid'};
ok( path_exists_by_dispatch( 'library/foowang.mc' ) );
ok( path_exists( $dbix_conn, 'library/foowang.mc' ) );
my $full_path_of_foowang = File::Spec->catfile( $comp_root, $status->payload->{path} );
ok( -o $full_path_of_foowang );
is( "wang wang wazoo", read_file( $full_path_of_foowang ) );
note( "update: expected behavior" );
$component_obj = '{ "path" : "library/foowang.mc", "source" : "this is only a test", "acl" : "inactive" }';
req( $test, 403, 'demo', 'POST', $base, $component_obj );
$status = req( $test, 200, 'root', 'POST', $base, $component_obj );
t/dispatch/component.t view on Meta::CPAN
$weirded_object = '{ "path" : "!!!!!", "source" : "down it goes", "acl" : "inactive" }';
#$status = req( $test, 400, 'root', 'POST', $base, $weirded_object );
#like( $status->text, qr/check constraint "kosher_path"/ );
dbi_err( $test, 500, 'root', 'POST', $base, $weirded_object, qr/check constraint "kosher_path"/ );
$illegal_acl = '{ "path" : "library/machinations.mc", "source" : "wang wang wazoo", "acl" : "puppy" }';
req( $test, 400, 'root', 'POST', $base, $illegal_acl );
note( "delete the testing component" );
ok( -e $full_path_of_foowang );
delete_testing_component( $cid_of_foowang );
ok( ! path_exists_by_dispatch( 'library/foowang.mc' ) );
ok( ! path_exists( $dbix_conn, 'library/foowang.mc' ) );
ok( ! -e $full_path_of_foowang );
note( "DELETE on $base" );
foreach my $user ( qw( demo active puppy root ) ) {
req( $test, 405, $user, 'DELETE', $base );
}
done_testing;
t/model/component.t view on Meta::CPAN
#
#!perl
use 5.012;
use strict;
use warnings;
#use App::CELL::Test::LogToFile;
use App::CELL qw( $meta $site );
use Data::Dumper;
use App::Dochazka::REST::ConnBank qw( $dbix_conn );
use App::Dochazka::REST::Model::Component qw( cid_by_path cid_exists path_exists );
use App::Dochazka::REST::Test;
use Test::Fatal;
use Test::More;
use Test::Warnings;
note( "initialize, connect to database, and set up a testing plan" );
initialize_regression_test();
note( 'spawn two component objects' );
t/model/component.t view on Meta::CPAN
ok( $comp->compare( $comp2 ) ); # still the same
ok( $comp2->compare( $comp ) );
$comp2->source( "jine fody" );
ok( ! $comp->compare( $comp2 ) ); # different
note( 'reset the activities' );
$comp->reset;
$comp2->reset;
ok( $comp->compare( $comp2 ) );
foreach my $prop ( qw( cid path source acl ) ) {
is( $comp->{$prop}, undef );
is( $comp2->{$prop}, undef );
}
note( 'test existence and viability of initial set of components' );
note( 'this also conducts positive tests of load_by_path and load_by_cid' );
foreach my $compdef ( @{ $site->DOCHAZKA_COMPONENT_DEFINITIONS } ) {
my $status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, $compdef->{path} );
is( $status->code, 'DISPATCH_RECORDS_FOUND' );
is( $status->level, 'OK' );
$comp = $status->payload;
is( $comp->path, $compdef->{path} );
is( $comp->source, $compdef->{source} );
is( $comp->acl, $compdef->{acl} );
$status = App::Dochazka::REST::Model::Component->load_by_cid( $dbix_conn, $comp->cid );
is( $status->level, 'OK' );
is( $status->code, 'DISPATCH_RECORDS_FOUND' );
$comp2 = $status->payload;
is_deeply( $comp, $comp2 );
}
note( 'test some bad parameters' );
like( exception { $comp2->load_by_cid( $dbix_conn, undef ) },
qr/not one of the allowed types/ );
like( exception { $comp2->load_by_path( $dbix_conn, undef ) },
qr/not one of the allowed types/ );
like( exception { App::Dochazka::REST::Model::Component->load_by_cid( $dbix_conn, undef ) },
qr/not one of the allowed types/ );
like( exception { App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, undef ) },
qr/not one of the allowed types/ );
note( 'load non-existent component' );
my $status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, 'orneryFooBarred' );
is( $status->level, 'NOTICE' );
is( $status->code, 'DISPATCH_NO_RECORDS_FOUND' );
ok( ! exists( $status->{'payload'} ) );
ok( ! defined( $status->payload ) );
note( 'load existent component' );
$status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, 'sample/local_time.mc' );
is( $status->level, 'OK' );
is( $status->code, 'DISPATCH_RECORDS_FOUND' );
my $sample_component = $status->payload;
ok( $sample_component->cid );
ok( $sample_component->path );
is( $sample_component->path, 'sample/local_time.mc' );
my $sample_component_cid = cid_by_path( $dbix_conn, 'sample/local_time.mc' );
is( $sample_component_cid, $sample_component->cid );
like ( exception { $sample_component_cid = cid_by_path( $dbix_conn, ( 1..6 ) ); },
qr/but 2 were expected/ );
is( cid_by_path( $dbix_conn, 'orneryFooBarred' ), undef, 'cid_by_path returns undef if path does not exist' );
note( 'insert a component (success)' );
my $non_bogus_component = App::Dochazka::REST::Model::Component->spawn(
path => 'non/bogus',
source => 'An componnennt',
acl => 'passerby',
);
note( "About to insert non_bogus_component" );
$status = $non_bogus_component->insert( $faux_context );
if ( $status->not_ok ) {
diag( Dumper $status );
BAIL_OUT(0);
}
is( $status->level, 'OK' );
ok( defined( $non_bogus_component->cid ) );
ok( $non_bogus_component->cid > 0 );
is( $non_bogus_component->path, 'non/bogus' );
is( $non_bogus_component->source, "An componnennt" );
is( $non_bogus_component->acl, 'passerby' );
note( 'try to insert the same component again (fail with DOCHAZKA_DBI_ERR)' );
$status = $non_bogus_component->insert( $faux_context );
ok( $status->not_ok );
is( $status->level, 'ERR' );
is( $status->code, 'DOCHAZKA_DBI_ERR' );
like( $status->text, qr#Key \(path\)\=\(non/bogus\) already exists# );
t/model/component.t view on Meta::CPAN
is( $status->code, 'DOCHAZKA_CUD_OK' );
note( 'load it and compare it' );
$status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, $non_bogus_component->path );
is( $status->code, 'DISPATCH_RECORDS_FOUND' );
my $bc2 = $status->payload;
is( $bc2->path, 'bogosITYVille' );
is( $bc2->source, "A bogus component that doesn't belong here" );
is( $bc2->acl, 'inactive' );
my $cid_of_non_bogus_component = $non_bogus_component->cid;
my $path_of_non_bogus_component = $non_bogus_component->path;
ok( cid_exists( $dbix_conn, $cid_of_non_bogus_component ) );
ok( path_exists( $dbix_conn, $path_of_non_bogus_component ) );
note( 'CLEANUP: delete the bogus component' );
#diag( "About to delete non_bogus_component" );
$status = $non_bogus_component->delete( $faux_context );
if ( $status->not_ok ) {
diag( Dumper $status );
BAIL_OUT(0);
}
is( $status->level, 'OK' );
ok( ! cid_exists( $dbix_conn, $cid_of_non_bogus_component ) );
ok( ! path_exists( $dbix_conn, $path_of_non_bogus_component ) );
note( 'attempt to load the bogus component - no longer there' );
$status = App::Dochazka::REST::Model::Component->load_by_cid( $dbix_conn, $cid_of_non_bogus_component );
is( $status->level, 'NOTICE' );
is( $status->code, 'DISPATCH_NO_RECORDS_FOUND' );
$status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, $path_of_non_bogus_component );
is( $status->level, 'NOTICE' );
is( $status->code, 'DISPATCH_NO_RECORDS_FOUND' );
$status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, 'boguS' );
is( $status->level, 'NOTICE' );
is( $status->code, 'DISPATCH_NO_RECORDS_FOUND' );
$status = App::Dochazka::REST::Model::Component->load_by_path( $dbix_conn, 'bogosITYVille' );
is( $status->level, 'NOTICE' );