From 94583f61bf98740cebb5afecbfe1c114e9a2c57d Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Thu, 20 Apr 2017 01:27:18 +0100 Subject: [PATCH] Refactored entire api auth code, and upload endpoint --- lib/Pear/LocalLoop.pm | 25 +- lib/Pear/LocalLoop/Controller/Api/Admin.pm | 21 +- lib/Pear/LocalLoop/Controller/Api/Auth.pm | 70 ++-- lib/Pear/LocalLoop/Controller/Api/Upload.pm | 373 ++++++++------------ lib/Pear/LocalLoop/Plugin/Validators.pm | 11 + t/admin-approve.t | 8 +- t/register.t | 2 +- t/upload.t | 124 +++---- 8 files changed, 283 insertions(+), 351 deletions(-) diff --git a/lib/Pear/LocalLoop.pm b/lib/Pear/LocalLoop.pm index a453e60..dae393a 100644 --- a/lib/Pear/LocalLoop.pm +++ b/lib/Pear/LocalLoop.pm @@ -51,6 +51,20 @@ sub startup { $self->helper( db => sub { $self->app->schema->storage->dbh }); $self->helper( schema => sub { $self->app->schema }); + $self->helper( api_validation_error => sub { + my $c = shift; + my $failed_vals = $c->validation->failed; + for my $val ( @$failed_vals ) { + my $check = shift @{ $c->validation->error($val) }; + return $c->render( + json => { + success => Mojo::JSON->false, + message => $c->error_messages->{$val}->{$check}->{message}, + }, + status => $c->error_messages->{$val}->{$check}->{status}, + ); + } + }); my $r = $self->routes; $r->get('/')->to('root#index'); @@ -60,11 +74,14 @@ sub startup { $r->any('/logout')->to('root#auth_logout'); # Always available api routes - $r->post('api/login')->to('api-auth#post_login'); - $r->post('api/register')->to('api-register#post_register'); - $r->post('api/logout')->to('api-auth#post_logout'); + my $api_public = $r->under('/api')->to('api-auth#check_json'); - my $api = $r->under('/api')->to('api-auth#auth'); + $api_public->post('/login')->to('api-auth#post_login'); + $api_public->post('/register')->to('api-register#post_register'); + $api_public->post('/logout')->to('api-auth#post_logout'); + + # Private, must be authenticated api routes + my $api = $api_public->under('/')->to('api-auth#auth'); $api->post('/' => sub { return shift->render( json => { diff --git a/lib/Pear/LocalLoop/Controller/Api/Admin.pm b/lib/Pear/LocalLoop/Controller/Api/Admin.pm index 0cdcdb1..f9e0d54 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Admin.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Admin.pm @@ -2,9 +2,28 @@ package Pear::LocalLoop::Controller::Api::Admin; use Mojo::Base 'Mojolicious::Controller'; use Data::Dumper; +sub auth { + my $c = shift; + + if ( defined $c->stash->{ api_user }->administrator ) { + return 1; + } + + $c->render( + json => { + success => Mojo::JSON->false, + message => 'Not Authorised', + }, + status => 403, + ); + return 0; +} sub post_admin_approve { - my $self = shift; + my $c = shift; + my $self = $c; + + my $user = $c->stash->{ api_user }; my $userId = $self->get_active_user_id(); if ( ! $self->is_admin($userId) ) { diff --git a/lib/Pear/LocalLoop/Controller/Api/Auth.pm b/lib/Pear/LocalLoop/Controller/Api/Auth.pm index 59f3fe5..43ecfae 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Auth.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Auth.pm @@ -15,27 +15,41 @@ has error_messages => sub { }; }; +sub check_json { + my $c = shift; + + # JSON object is either the whole request, or under a json param for upload + my $json = $c->req->json || decode_json( $c->param('json') || '{}' ); + + unless ( defined $json && ref $json eq 'HASH' && scalar( keys %$json ) > 0 ) { + $c->render( + json => { + success => Mojo::JSON->false, + message => 'JSON is missing.', + }, + status => 400, + ); + return 0; + } + + $c->stash( api_json => $json ); + return 1; +} + sub auth { my $c = shift; - my $session_key = $c->req->json( '/session_key' ); + my $session_key = $c->stash->{api_json}->{session_key}; - unless ( defined $session_key ) { - # Upload doesnt quite use json correctly.... - my $json = $c->param('json'); - if ( defined $json ) { - $json = decode_json( $json ); - $session_key = $json->{session_key}; + if ( defined $session_key ) { + my $session_result = $c->schema->resultset('SessionToken')->find({ sessiontokenname => $session_key }); + + if ( defined $session_result ) { + $c->stash( api_user => $session_result->user ); + return 1; } } - my $session_result = $c->schema->resultset('SessionToken')->find({ sessiontokenname => $session_key }); - - if ( defined $session_result ) { - $c->stash( api_user => $session_result->user ); - return 1; - } - $c->render( json => { success => Mojo::JSON->false, @@ -51,37 +65,15 @@ sub post_login { my $validation = $c->validation; - my $json = $c->req->json; - - if ( ! defined $json ){ - return $c->render( json => { - success => Mojo::JSON->false, - message => 'No json sent.', - }, - status => 400); #Malformed request - } - - $validation->input( $json ); + $validation->input( $c->stash->{api_json} ); $validation->required('email')->email; $validation->required('password'); + return $c->api_validation_error if $validation->has_error; + my $email = $validation->param('email'); my $password = $validation->param('password'); - if ( $validation->has_error ) { - my $failed_vals = $validation->failed; - for my $val ( @$failed_vals ) { - my $check = shift @{ $validation->error($val) }; - return $c->render( - json => { - success => Mojo::JSON->false, - message => $c->error_messages->{$val}->{$check}->{message}, - }, - status => $c->error_messages->{$val}->{$check}->{status}, - ); - } - } - my $user_result = $c->schema->resultset('User')->find({ email => $email }); if ( defined $user_result ) { diff --git a/lib/Pear/LocalLoop/Controller/Api/Upload.pm b/lib/Pear/LocalLoop/Controller/Api/Upload.pm index e124a83..112242d 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Upload.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Upload.pm @@ -11,97 +11,115 @@ The json string should be an object, with the following keys: =over -=item * microCurrencyValue +=item * transaction_value The value of the transaction -=item * transactionAdditionType +=item * transaction_type Is a value of 1, 2, or 3 - depending on the type of transaction. -=item * addValidatedId +=item * organisation_id -An ID of a valid organisation. used when transactionAdditionType is 1. +An ID of a valid organisation. used when transaction_type is 1 or 2. -=item * addUnvalidatedId +=item * organisation_name -An ID of an unvalidated organisation. Used when transactionAdditionType is 2. +The name of an organisation. Used when transaction_type is 3. -=item * organisationName +=item * street_name -The name of an organisation. Used when transactionAdditionType is 3. +The street of an organisation, optional key. Used when transaction_type is 3. + +=item * town + +The village/town/city of an organisation. Used when transaction_type is 3. + +=item * postcode + +The postcode of an organisation, optional key. Used when transaction_Type is 3. =back =cut +has error_messages => sub { + return { + transactionAdditionType => { + required => { message => 'transactionAdditionType is missing.', status => 400 }, + in => { message => 'transactionAdditionType is not a valid value.', status => 400 }, + }, + microCurrencyValue => { + required => { message => 'microCurrencyValue is missing', status => 400 }, + number => { message => 'microCurrencyValue does not look like a number', status => 400 }, + gt_num => { message => 'microCurrencyValue cannot be equal to or less than zero', status => 400 }, + }, + file2 => { + required => { message => 'No file uploaded', status => 400 }, + }, + addValidatedId => { + required => { message => 'addValidatedId is missing', status => 400 }, + number => { message => 'organisation_id is not a number', status => 400 }, + in_resultset => { message => 'addValidatedId does not exist in the database', status => 400 }, + }, + addUnvalidatedId => { + required => { message => 'addUnvalidatedId is missing', status => 400 }, + number => { message => 'addUnvalidatedId does not look like a number', status => 400 }, + in_resultset => { message => 'addUnvalidatedId does not exist in the database for the user', status => 400 }, + }, + organisationName => { + required => { message => 'organisationName is missing', status => 400 }, + }, + }; +}; + sub post_upload { - my $self = shift; + my $c = shift; + my $self = $c; - my $userId = $self->stash->{api_user}->id; + my $user = $c->stash->{api_user}; - my $json = $self->param('json'); - if ( ! defined $json ) { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'JSON is missing.', - }, - status => 400,); #Malformed request + my $validation = $c->validation; + + # Test for file before loading the JSON in to the validator + $validation->required('file2'); + + $validation->input( $c->stash->{api_json} ); + + $validation->required('microCurrencyValue')->number->gt_num(0); + $validation->required('transactionAdditionType')->in( 1, 2, 3 ); + + # First pass of required items + return $c->api_validation_error if $validation->has_error; + + my $type = $validation->param('transactionAdditionType'); + + if ( $type == 1 ) { + # Validated Organisation + my $valid_org_rs = $c->schema->resultset('Organisation'); + $validation->required('addValidatedId')->number->in_resultset( 'organisationalid', $valid_org_rs ); + } elsif ( $type == 2 ) { + # Unvalidated Organisation + my $valid_org_rs = $c->schema->resultset('PendingOrganisation')->search({ usersubmitted_fk => $user->id }); + $validation->required('addUnvalidatedId')->number->in_resultset( 'pendingorganisationid', $valid_org_rs ); + } elsif ( $type == 3 ) { + # Unknown Organisation + $validation->required('organisationName'); + $validation->optional('streetName'); + $validation->optional('town'); + $validation->optional('postcode')->postcode; } - $json = Mojo::JSON::decode_json($json); - $self->app->log->debug( "JSON: " . Dumper $json ); - - my $microCurrencyValue = $json->{microCurrencyValue}; - if ( ! defined $microCurrencyValue ) { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'microCurrencyValue is missing.', - }, - status => 400,); #Malformed request - } - #Is valid number - elsif (! Scalar::Util::looks_like_number($microCurrencyValue)){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'microCurrencyValue does not look like a number.', - }, - status => 400,); #Malformed request - } - #Is the number range valid. - elsif ($microCurrencyValue <= 0){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'microCurrencyValue cannot be equal to or less than zero.', - }, - status => 400,); #Malformed request - } + return $c->api_validation_error if $validation->has_error; - my $transactionAdditionType = $json->{transactionAdditionType}; - if ( ! defined $transactionAdditionType ) { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'transactionAdditionType is missing.', - }, - status => 400,); #Malformed request - } + my $transactionAdditionType = $type; + my $microCurrencyValue = $validation->param('microCurrencyValue'); + my $json = $c->stash->{api_json}; + + my $userId = $user->id; + my $file = $self->req->upload('file2'); - $self->app->log->debug( "file: " . Dumper $file ); - - if (! defined $file) { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'no file uploaded.', - }, - status => 400,); #Malformed request - } my $ext = '.jpg'; my $uuid = Data::UUID->new->create_str; @@ -118,185 +136,72 @@ sub post_upload { # }, status => 400); # }; - #Add validated organisation. - if ($transactionAdditionType == 1){ + if ( $type == 1 ) { + # Validated organisation + $c->schema->resultset('Transaction')->create({ + buyeruserid_fk => $user->id, + sellerorganisationid_fk => $validation->param('addValidatedId'), + valuemicrocurrency => $microCurrencyValue, + proofimage => $filename, + timedatesubmitted => DateTime->now, + }); - my $addValidatedId = $json->{addValidatedId}; - if (! defined $addValidatedId){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'addValidatedId is missing.', - }, - status => 400,); #Malformed request + $file->move_to('images/' . $filename); + } elsif ( $type == 2 ) { + # Unvalidated Organisation + $c->schema->resultset('PendingTransaction')->create({ + buyeruserid_fk => $user->id, + pendingsellerorganisationid_fk => $validation->param('addUnvalidatedId'), + valuemicrocurrency => $microCurrencyValue, + proofimage => $filename, + timedatesubmitted => DateTime->now, + }); + + $file->move_to('images/' . $filename); + } elsif ( $type == 3 ) { + my $organisationName = $validation->param('organisationName'); + my $streetName = $validation->param('streetName'); + my $town = $validation->param('town'); + my $postcode = $validation->param('postcode'); + + my $fullAddress = ""; + + if ( defined $streetName && ! ($streetName =~ m/^\s*$/) ){ + $fullAddress = $streetName; } - if (! $self->does_organisational_id_exist($addValidatedId)){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'addValidatedId does not exist in the database.', - }, - status => 400,); #Malformed request - } - - my $time = time(); - my $statement = $self->db->prepare("INSERT INTO Transactions (BuyerUserId_FK, SellerOrganisationId_FK, ValueMicroCurrency, ProofImage, TimeDateSubmitted) VALUES (?, ?, ?, ?, ?)"); - my $rowsAdded = $statement->execute($userId, $addValidatedId, $microCurrencyValue, $filename, $time); - - #It was successful. - if ($rowsAdded != 0) { - $file->move_to('images/' . $filename); - $self->app->log->debug('Path Success: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->true, - message => 'Added transaction for validated organisation.', - }, - status => 200,); - } - #TODO Untested, not quite sure how to test it. - else { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'An unknown error occurred when adding the transaction.', - }, - status => 500,); - } - } - #2 and 3 are similar by the adding of a transaction at the end. - elsif ($transactionAdditionType == 2 || $transactionAdditionType == 3){ - - my $unvalidatedOrganisationId = undef; - - if ($transactionAdditionType == 2){ - $self->app->log->debug('Path: file:' . __FILE__ . ', line: ' . __LINE__); - - $unvalidatedOrganisationId = $json->{addUnvalidatedId}; - if (! defined $unvalidatedOrganisationId){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'addUnvalidatedId is missing.', - }, - status => 400,); #Malformed request - } - elsif (! Scalar::Util::looks_like_number($unvalidatedOrganisationId)){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'addUnvalidatedId does not look like a number.', - }, - status => 400,); #Malformed request - } - - my ($existsRef) = $self->db->selectrow_array("SELECT COUNT(PendingOrganisationId) FROM PendingOrganisations WHERE PendingOrganisationId = ? AND UserSubmitted_FK = ?",undef,($unvalidatedOrganisationId, $userId)); - if ($existsRef == 0) { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'addUnvalidatedId does not exist in the database for the user.', - }, - status => 400,); #Malformed request - } - - } - #type need to add a organisation for type 3. - else{ # ($transactionAdditionType == 3) - $self->app->log->debug('Path: file:' . __FILE__ . ', line: ' . __LINE__); - - #TODO more validation. - my $organisationName = $json->{organisationName}; - if (! defined $organisationName){ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'organisationName is missing.', - }, - status => 400,); #Malformed request - } - - #TODO validation. - #TODO check which ones are present. - my $streetName = $json->{streetName}; - my $town = $json->{town}; - my $postcode = $json->{postcode}; - - ($unvalidatedOrganisationId) = $self->db->selectrow_array("SELECT MAX(PendingOrganisationId) FROM PendingOrganisations",undef,()); - if (defined $unvalidatedOrganisationId){ - $unvalidatedOrganisationId++; + if ( defined $town && ! ($town =~ m/^\s*$/) ){ + if ($fullAddress eq ""){ + $fullAddress = $town; } else{ - $unvalidatedOrganisationId = 1; + $fullAddress = $fullAddress . ", " . $town; } - my $fullAddress = ""; - - if ( defined $streetName && ! ($streetName =~ m/^\s*$/) ){ - $fullAddress = $streetName; - } - - if ( defined $town && ! ($town =~ m/^\s*$/) ){ - if ($fullAddress eq ""){ - $fullAddress = $town; - } - else{ - $fullAddress = $fullAddress . ", " . $town; - } - - } - - my $statement = $self->db->prepare("INSERT INTO PendingOrganisations (PendingOrganisationId, UserSubmitted_FK, TimeDateSubmitted, Name, FullAddress, Postcode) VALUES (?, ?, ?, ?, ?, ?)"); - my $rowsAdded = $statement->execute($unvalidatedOrganisationId,$userId,time(),$organisationName,$fullAddress,$postcode); - - #TODO, untested. It could not be added for some reason. Most likely race conditions. - if ($rowsAdded == 0) { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'An unknown error occurred when adding the transaction.', - }, - status => 500,); - } } + my $pending_org = $c->schema->resultset('PendingOrganisation')->create({ + usersubmitted_fk => $user->id, + timedatesubmitted => DateTime->now, + name => $organisationName, + fulladdress => $fullAddress, + postcode => $postcode, + }); - my $statement2 = $self->db->prepare("INSERT INTO PendingTransactions (BuyerUserId_FK, PendingSellerOrganisationId_FK, ValueMicroCurrency, ProofImage, TimeDateSubmitted) VALUES (?, ?, ?, ?, ?)"); - my $rowsAdded2 = $statement2->execute($userId, $unvalidatedOrganisationId, $microCurrencyValue, $filename, time()); + $c->schema->resultset('PendingTransaction')->create({ + buyeruserid_fk => $user->id, + pendingsellerorganisationid_fk => $pending_org->pendingorganisationid, + valuemicrocurrency => $microCurrencyValue, + proofimage => $filename, + timedatesubmitted => DateTime->now, + }); - if ($rowsAdded2 != 0) { - $file->move_to('images/' . $filename); - $self->app->log->debug('Path Success: file:' . __FILE__ . ', line: ' . __LINE__); - - my $returnedJson = { - success => Mojo::JSON->true, - message => 'Added transaction for unvalidated organisation.', - }; - - if ($transactionAdditionType == 3){ - $returnedJson->{unvalidatedOrganisationId} = $unvalidatedOrganisationId; - } - - return $self->render( json => $returnedJson, - status => 200,); - } - else { - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'An unknown error occurred when adding the transaction.', - }, - status => 500,); - } - } - else{ - $self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__); - return $self->render( json => { - success => Mojo::JSON->false, - message => 'transactionAdditionType is not a valid value.', - }, - status => 400,); #Malformed request + $file->move_to('images/' . $filename); } + return $self->render( json => { + success => Mojo::JSON->true, + message => 'Upload Successful', + }); } diff --git a/lib/Pear/LocalLoop/Plugin/Validators.pm b/lib/Pear/LocalLoop/Plugin/Validators.pm index 64e000c..c977420 100644 --- a/lib/Pear/LocalLoop/Plugin/Validators.pm +++ b/lib/Pear/LocalLoop/Plugin/Validators.pm @@ -3,6 +3,7 @@ use Mojo::Base 'Mojolicious::Plugin'; use Email::Valid; use Geo::UK::Postcode; +use Scalar::Util qw/ looks_like_number /; sub register { my ( $plugin, $app, $conf ) = @_; @@ -26,6 +27,16 @@ sub register { my ( $validation, $name, $value ) = @_; return Geo::UK::Postcode->new( $value )->valid ? undef : 1; }); + + $app->validator->add_check( number => sub { + my ( $validation, $name, $value ) = @_; + return looks_like_number( $value ) ? undef : 1; + }); + + $app->validator->add_check( gt_num => sub { + my ( $validation, $name, $value, $check ) = @_; + return $value > $check ? undef : 1; + }); } 1; diff --git a/t/admin-approve.t b/t/admin-approve.t index 5f247f7..73e61c7 100644 --- a/t/admin-approve.t +++ b/t/admin-approve.t @@ -146,7 +146,7 @@ $t->post_ok('/api/admin-approve' => json => $json) print "test 8 - Logout Reno\n"; -$t->post_ok('/api/logout') +$t->post_ok('/api/logout', json => { session_key => $session_key } ) ->status_is(200) ->json_is('/success', Mojo::JSON->true); @@ -284,7 +284,7 @@ $t->post_ok('/api/admin-approve' => json => $json) ->content_like(qr/You are not an admin/i); print "test 16 - Logout Choco Billy\n"; -$t->post_ok('/api/logout') +$t->post_ok('/api/logout', json => { session_key => $session_key } ) ->status_is(200) ->json_is('/success', Mojo::JSON->true); @@ -306,9 +306,9 @@ $session_key = $t->tx->res->json('/session_key'); print "test 18 - JSON is missing.\n"; $t->post_ok('/api/admin-approve' => json) - ->status_is(401) + ->status_is(400) ->json_is('/success', Mojo::JSON->false) - ->json_like('/message', qr/Invalid Session/i); + ->json_like('/message', qr/JSON is missing/i); print "test 19 - unvalidatedOrganisationId missing (non-modify).\n"; $json = { diff --git a/t/register.t b/t/register.t index 511a382..41671e1 100644 --- a/t/register.t +++ b/t/register.t @@ -22,7 +22,7 @@ $schema->resultset('AccountToken')->populate([ $t->post_ok('/api/register') ->status_is(400) ->json_is('/success', Mojo::JSON->false) - ->content_like(qr/no json sent/i); + ->json_like('/message', qr/JSON is missing/i); #Empty JSON my $testJson = {}; diff --git a/t/upload.t b/t/upload.t index 9d3b522..afde937 100644 --- a/t/upload.t +++ b/t/upload.t @@ -1,47 +1,36 @@ +use Mojo::Base -strict; + use Test::More; -use Test::Mojo; use Mojo::JSON; +use Test::Pear::LocalLoop; -use FindBin; - -BEGIN { - $ENV{MOJO_MODE} = 'testing'; - $ENV{MOJO_LOG_LEVEL} = 'debug'; -} - -my $t = Test::Mojo->new("Pear::LocalLoop"); - -my $dbh = $t->app->db; - -#Dump all pf the test tables and start again. -my $sqlDeployment = Mojo::File->new("$FindBin::Bin/../dropschema.sql")->slurp; -for (split ';', $sqlDeployment){ - $dbh->do($_) or die $dbh->errstr; -} - -my $sqlDeployment = Mojo::File->new("$FindBin::Bin/../schema.sql")->slurp; -for (split ';', $sqlDeployment){ - $dbh->do($_) or die $dbh->errstr; -} +my $framework = Test::Pear::LocalLoop->new; +my $t = $framework->framework; +my $schema = $t->app->schema; my @accountTokens = ('a', 'b', 'c'); -my $tokenStatement = $dbh->prepare('INSERT INTO AccountTokens (AccountTokenName) VALUES (?)'); -foreach (@accountTokens){ - my $rowsAdded = $tokenStatement->execute($_); -} + +$schema->resultset('AccountToken')->populate([ + [ 'accounttokenname' ], + map { [ $_ ] } @accountTokens, +]); #Add one company that we've apparently authenticated but does not have an account. my $companyIdNumShinra = 1; my $name = "Shinra Electric Power Company"; my $fullAddress = "Sector 0, Midgar, Eastern Continent, Gaia"; my $postcode = "E1 M00"; -my $statementOrgIns = $t->app->db->prepare("INSERT INTO Organisations (OrganisationalId, Name, FullAddress, PostCode) VALUES (?, ?, ?, ?)"); - -is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations")}[0],0,"No organisations"; -$statementOrgIns->execute($companyIdNumShinra, $name, $fullAddress, $postcode); -is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations")}[0],1,"1 testing organisation"; +my $org_rs = $schema->resultset('Organisation'); +is $org_rs->count, 0, "No organisations"; +$org_rs->create({ + organisationalid => $companyIdNumShinra, + name => $name, + fulladdress => $fullAddress, + postcode => $postcode, +}); +is $org_rs->count, 1, "1 testing organisation"; #This depends on "register.t" and "login.t" working. @@ -65,7 +54,7 @@ $t->post_ok('/api/register' => json => $testJson) print "test 2 - Create customer user account (Hojo)\n"; my $emailHojo = 'hojo@shinra.energy'; my $passwordHojo = 'Mako'; -my $testJson = { +$testJson = { 'usertype' => 'customer', 'token' => shift(@accountTokens), 'username' => 'ProfessorHojo', @@ -81,7 +70,7 @@ $t->post_ok('/api/register' => json => $testJson) print "test 3 - Create organisation user account (Choco Billy)\n"; my $emailBilly = 'choco.billy@chocofarm.org'; my $passwordBilly = 'Choco'; -my $testJson = { +$testJson = { 'usertype' => 'organisation', 'token' => shift(@accountTokens), 'username' => 'ChocoBillysGreens', @@ -111,9 +100,9 @@ my $session_key = $t->tx->res->json('/session_key'); print "test 5 - JSON missing\n"; my $upload = {file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) - ->status_is(401) + ->status_is(400) ->json_is('/success', Mojo::JSON->false) - ->json_like('/message', qr/Invalid Session/); + ->json_like('/message', qr/JSON is missing/); #TODO Check for malformed JSON. @@ -123,46 +112,46 @@ my $json = { addValidatedId => $companyIdNumShinra, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) ->content_like(qr/microCurrencyValue is missing/i); print "test 7 - microCurrencyValue non-numbers\n"; -my $json = { +$json = { microCurrencyValue => 'Abc', transactionAdditionType => 1, addValidatedId => $companyIdNumShinra, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) ->content_like(qr/microCurrencyValue does not look like a number/i); print "test 8 - microCurrencyValue equal to zero\n"; -my $json = { +$json = { microCurrencyValue => 0, transactionAdditionType => 1, addValidatedId => $companyIdNumShinra, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) ->content_like(qr/microCurrencyValue cannot be equal to or less than zero/i); print "test 9 - microCurrencyValue less than zero\n"; -my $json = { +$json = { microCurrencyValue => -1, transactionAdditionType => 1, addValidatedId => $companyIdNumShinra, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -173,7 +162,7 @@ $json = { microCurrencyValue => 10, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -186,7 +175,7 @@ $json = { session_key => $session_key, # addValidatedId => $companyIdNumShinra }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -199,7 +188,7 @@ $json = { addValidatedId => 1, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json)}; +$upload = {json => Mojo::JSON::encode_json($json)}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -212,7 +201,7 @@ $json = { session_key => $session_key, # addValidatedId => $companyIdNumShinra }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -225,7 +214,7 @@ $json = { addValidatedId => ($companyIdNumShinra + 100), session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -239,11 +228,11 @@ $json = { addValidatedId => $companyIdNumShinra, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(200) ->json_is('/success', Mojo::JSON->true) - ->content_like(qr/Added transaction for validated organisation/i); + ->json_like('/message', qr/Upload Successful/); is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions")}[0],1,"1 transaction"; # Add type 3 (new organisation) checking. @@ -254,10 +243,10 @@ $json = { transactionAdditionType => 3, streetName => "Slums, Sector 7", town => "Midgar", - postcode => "E1 MS07", + postcode => "E1 0AA", session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -273,17 +262,14 @@ $json = { organisationName => '7th Heaven', streetName => "Slums, Sector 7", town => "Midgar", - postcode => "E1 MS07", + postcode => "E1 0AA", session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(200) ->json_is('/success', Mojo::JSON->true) - ->json_has('/unvalidatedOrganisationId') - ->content_like(qr/Added transaction for unvalidated organisation/i); -my $unvalidatedOrganisationId = $t->tx->res->json->{unvalidatedOrganisationId}; -is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations WHERE PendingOrganisationId = ?", undef, ($unvalidatedOrganisationId))}[0],1,"unvalidatedOrganisationId exists"; + ->json_like('/message', qr/Upload Successful/); is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations")}[0],1,"1 pending organisation"; is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],1,"1 pending transaction"; @@ -295,7 +281,7 @@ $json = { transactionAdditionType => 2, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -308,7 +294,7 @@ $json = { addUnvalidatedId => "Abc", session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -321,14 +307,14 @@ $json = { addUnvalidatedId => 1000, #Id that does not exist session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) ->content_like(qr/addUnvalidatedId does not exist in the database for the user/i); print "test 21 - Logout Rufus (type 2: existing organisation)\n"; -$t->post_ok('/api/logout') +$t->post_ok('/api/logout', json => { session_key => $session_key } ) ->status_is(200) ->json_is('/success', Mojo::JSON->true); @@ -349,6 +335,8 @@ $t->post_ok('/api/login' => json => $testJson) $session_key = $t->tx->res->json('/session_key'); print "test 23 - add valid transaction but for with account (type 2: existing organisation)\n"; +my $org_result = $schema->resultset('PendingOrganisation')->find({ name => '7th Heaven' }); +my $unvalidatedOrganisationId = $org_result->pendingorganisationid; is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],1,"1 pending transaction"; $json = { microCurrencyValue => 10, @@ -356,7 +344,7 @@ $json = { addUnvalidatedId => $unvalidatedOrganisationId, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(400) ->json_is('/success', Mojo::JSON->false) @@ -364,7 +352,7 @@ $t->post_ok('/api/upload' => form => $upload ) is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],1,"1 pending transaction"; print "test 24 - Logout Hojo\n"; -$t->post_ok('/api/logout') +$t->post_ok('/api/logout', json => { session_key => $session_key } ) ->status_is(200) ->json_is('/success', Mojo::JSON->true); @@ -392,16 +380,16 @@ $json = { addUnvalidatedId => $unvalidatedOrganisationId, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(200) ->json_is('/success', Mojo::JSON->true) - ->content_like(qr/Added transaction for unvalidated organisation./i); + ->json_like('/message', qr/Upload Successful/); is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],2,"2 pending transaction"; print "test 27 - Logout Rufus\n"; -$t->post_ok('/api/logout') +$t->post_ok('/api/logout' => json => { session_key => $session_key } ) ->status_is(200) ->json_is('/success', Mojo::JSON->true); @@ -429,11 +417,11 @@ $json = { addValidatedId => $companyIdNumShinra, session_key => $session_key, }; -my $upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; +$upload = {json => Mojo::JSON::encode_json($json), file2 => {file => './t/test.jpg'}}; $t->post_ok('/api/upload' => form => $upload ) ->status_is(200) ->json_is('/success', Mojo::JSON->true) - ->content_like(qr/Added transaction for validated organisation/i); + ->json_like('/message', qr/Upload Successful/); is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions")}[0],2,"2 transactions"; done_testing();