Merge pull request #4 from Pear-Trading/TBSliver/Major-Rework

Major Rework
This commit is contained in:
Finn 2017-04-24 13:00:16 +01:00 committed by GitHub
commit 2acee95d86
54 changed files with 1430 additions and 3271 deletions

13
.travis.yml Normal file
View file

@ -0,0 +1,13 @@
sudo: false
language: perl
perl:
- "5.20"
env:
- HARNESS_PERL_SWITCHES="-MDevel::Cover"
install:
- cpanm --quiet --notest --installdeps .
- cpanm Devel::Cover
script:
- prove -lr
- cover

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# Pear LocalLoop Server
[![Build Status](https://travis-ci.org/Pear-Trading/Foodloop-Server.svg?branch=master)](https://travis-ci.org/Pear-Trading/Foodloop-Server)

View file

@ -10,8 +10,9 @@ requires 'Time::Fake';
requires 'Scalar::Util';
requires 'DBIx::Class';
requires 'DBIx::Class::PassphraseColumn';
requires 'DBIx::Class::TimeStamp';
requires 'DBIx::Class::Schema::Loader';
requires 'SQL::Translator';
requires 'DateTime';
requires 'DateTime::Format::Strptime';
requires 'DateTime::Format::SQLite';
requires 'TryCatch';

View file

@ -3,9 +3,10 @@ package Pear::LocalLoop;
use Mojo::Base 'Mojolicious';
use Data::UUID;
use Mojo::JSON;
use Scalar::Util qw(looks_like_number);
use Pear::LocalLoop::Schema;
use DateTime;
use Mojo::Asset::File;
use Mojo::File qw/ path tempdir /;
has schema => sub {
my $c = shift;
@ -21,6 +22,7 @@ sub startup {
$self->plugin('Config', {
default => {
storage_path => tempdir,
sessionTimeSeconds => 60 * 60 * 24 * 7,
sessionTokenJsonName => 'session_key',
sessionExpiresJsonName => 'sessionExpires',
@ -40,7 +42,7 @@ sub startup {
my $user = $c->schema->resultset('User')->find({email => $email});
if ( defined $user ) {
if ( $user->check_password( $password ) ) {
return $user->userid;
return $user->id;
}
}
return undef;
@ -48,7 +50,7 @@ sub startup {
});
# shortcut for use in template
$self->helper( db => sub { $self->app->schema->storage->dbh });
$self->helper( db => sub { warn "DEPRECATED db helper"; return $self->app->schema->storage->dbh });
$self->helper( schema => sub { $self->app->schema });
$self->helper( api_validation_error => sub {
@ -60,12 +62,46 @@ sub startup {
json => {
success => Mojo::JSON->false,
message => $c->error_messages->{$val}->{$check}->{message},
error => $check,
},
status => $c->error_messages->{$val}->{$check}->{status},
);
}
});
$self->helper( datetime_formatter => sub {
my $c = shift;
return DateTime::Format::Strptime->new(
pattern => '%FT%T%z',
strict => 1,
on_error => 'undef',
);
});
$self->helper( get_path_from_uuid => sub {
my $c = shift;
my $uuid = shift;
my ( $folder ) = $uuid =~ /(..)/;
return path($c->app->config->{storage_path}, $folder, $uuid);
});
$self->helper( store_file_from_upload => sub {
my $c = shift;
my $upload = shift;
my $uuid = Data::UUID->new->create_str;
my $path = $c->get_path_from_uuid( $uuid );
$path->dirname->make_path;
$upload->move_to( $path );
return $uuid;
});
$self->helper( get_file_from_uuid => sub {
my $c = shift;
my $uuid = shift;
return Mojo::Asset::File->new( path => $c->get_path_from_uuid( $uuid ) );
});
my $r = $self->routes;
$r->get('/')->to('root#index');
$r->post('/')->to('root#auth_login');
@ -73,6 +109,9 @@ sub startup {
$r->post('/register')->to('register#register');
$r->any('/logout')->to('root#auth_logout');
my $api_public_get = $r->under('/api');
$api_public_get->get('/info/ages')->to('api-info#get_ages');
# Always available api routes
my $api_public = $r->under('/api')->to('api-auth#check_json');
@ -91,117 +130,68 @@ sub startup {
});
$api->post('/upload')->to('api-upload#post_upload');
$api->post('/search')->to('api-upload#post_search');
$api->post('/admin-approve')->to('api-admin#post_admin_approve');
$api->post('/admin-merge')->to('api-admin#post_admin_merge');
$api->post('/user/day')->to('api-user#post_day');
$api->post('/edit')->to('api-api#post_edit');
$api->post('/fetchuser')->to('api-api#post_fetchuser');
$api->post('/user-history')->to('api-user#post_user_history');
my $api_admin = $api->under('/')->to('api-admin#auth');
$api_admin->post('/admin-approve')->to('api-admin#post_admin_approve');
$api_admin->post('/admin-merge')->to('api-admin#post_admin_merge');
my $admin_routes = $r->under('/admin')->to('admin#under');
$admin_routes->get('/')->to('admin#home');
$admin_routes->get('/tokens')->to('admin-tokens#index');
$admin_routes->post('/tokens')->to('admin-tokens#create');
$admin_routes->get('/tokens/:id')->to('admin-tokens#read');
$admin_routes->post('/tokens/:id')->to('admin-tokens#update');
$admin_routes->post('/tokens/:id/delete')->to('admin-tokens#delete');
$admin_routes->get('/users')->to('admin-users#index');
$admin_routes->get('/users/:id')->to('admin-users#read');
$admin_routes->post('/users/:id')->to('admin-users#update');
$admin_routes->post('/users/:id/delete')->to('admin-users#delete');
$admin_routes->get('/organisations')->to('admin-organisations#list');
$admin_routes->get('/organisations/valid/:id')->to('admin-organisations#valid_read');
$admin_routes->get('/organisations/pending/:id')->to('admin-organisations#pending_read');
$admin_routes->get('/organisations/pending/:id/approve')->to('admin-organisations#pending_approve');
my $user_routes = $r->under('/')->to('root#under');
$user_routes->get('/home')->to('root#home');
my $portal_api = $r->under('/portal')->to('api-auth#check_json')->under('/')->to('portal#under');
$portal_api->post('/upload')->to('api-upload#post_upload');
$portal_api->post('/search')->to('api-upload#post_search');
$self->hook( before_dispatch => sub {
my $self = shift;
$self->res->headers->header('Access-Control-Allow-Origin' => '*') if $self->app->mode eq 'development';
});
$self->helper( is_admin => sub {
my ($c, $user_id) = @_;
my $admin = $c->schema->resultset('Administrator')->find($user_id);
return defined $admin;
});
$self->helper( copy_transactions_and_delete => sub {
my ( $c, $from_org, $to_org ) = @_;
$self->helper( create_hash => sub{
my ($self, $id, $name, $fullAddress, $postcode) = @_;
my $from_org_transaction_rs = $from_org->transactions;
return {
id => $id,
name => $name,
fullAddress => $fullAddress . ", " . $postcode,
}
});
$self->helper(get_active_user_id => sub {
my $self = shift;
my $token = $self->get_session_token();
if (! defined $token){
return undef;
while ( my $from_org_transaction = $from_org_transaction_rs->next ) {
$to_org->create_related(
'transactions', {
buyer_id => $from_org_transaction->buyer_id,
value => $from_org_transaction->value,
proof_image => $from_org_transaction->proof_image,
submitted_at => $from_org_transaction->submitted_at,
}
);
}
my @out = $self->db->selectrow_array("SELECT UserIdAssignedTo_FK FROM SessionTokens WHERE SessionTokenName = ?",undef,($token));
if (! @out){
return undef;
}
else{
return $out[0];
}
});
$self->helper(get_session_token => sub {
my $self = shift;
#See if logged in.
my $sessionToken = undef;
my $json = $self->req->json;
if (defined $json) {
$sessionToken = $json->{$self->app->config->{sessionTokenJsonName}};
}
if ( ! defined $sessionToken || $sessionToken eq "" ) {
$sessionToken = $self->session->{$self->app->config->{sessionTokenJsonName}};
}
if (defined $sessionToken && $sessionToken eq "" ) {
$sessionToken = undef;
}
return $sessionToken;
});
#This assumes the user has no current session on that device.
$self->helper(generate_session => sub {
my ($self, $userId) = @_;
my $sessionToken = $self->generate_session_token();
my $insertStatement = $self->db->prepare('INSERT INTO SessionTokens (SessionTokenName, UserIdAssignedTo_FK, ExpireDateTime) VALUES (?, ?, ?)');
my $rowsAdded = $insertStatement->execute($sessionToken, $userId, DateTime->now()->add( years => 1 ));
return $sessionToken;
});
$self->helper(generate_session_token => sub {
my $self = shift;
return Data::UUID->new->create_str();
});
$self->helper(does_organisational_id_exist => sub {
my ( $c, $org_id ) = @_;
return defined $c->schema->resultset('Organisation')->find({ organisationalid => $org_id });
});
$self->helper(get_age_foreign_key => sub {
my ( $c, $age_string ) = @_;
my $age_range = $c->schema->resultset('AgeRange')->find({ agerangestring => $age_string });
return defined $age_range ? $age_range->agerangeid : undef;
$from_org->delete;
});
}

View file

@ -18,12 +18,16 @@ sub home {
my $user_rs = $c->schema->resultset('User');
my $token_rs = $c->schema->resultset('AccountToken');
my $pending_orgs_rs = $c->schema->resultset('PendingOrganisation');
my $pending_transaction_rs = $c->schema->resultset('PendingTransaction');
$c->stash(
user_count => $user_rs->count,
tokens => {
total => $token_rs->count,
unused => $token_rs->search({used => 0 })->count,
unused => $token_rs->search({ used => 0 })->count,
},
pending_orgs => $pending_orgs_rs->count,
pending_trans => $pending_transaction_rs->count,
);
}

View file

@ -0,0 +1,42 @@
package Pear::LocalLoop::Controller::Admin::Organisations;
use Mojo::Base 'Mojolicious::Controller';
sub list {
my $c = shift;
my $valid_orgs_rs = $c->schema->resultset('Organisation');
my $pending_orgs_rs = $c->schema->resultset('PendingOrganisation');
$c->stash(
valid_orgs_rs => $valid_orgs_rs,
pending_orgs_rs => $pending_orgs_rs,
);
}
sub valid_read {
my $c = shift;
my $valid_org = $c->schema->resultset('Organisation')->find( $c->param('id') );
$c->stash( valid_org => $valid_org );
}
sub pending_read {
my $c = shift;
my $pending_org = $c->schema->resultset('PendingOrganisation')->find( $c->param('id') );
$c->stash( pending_org => $pending_org );
}
sub pending_approve {
my $c = shift;
my $pending_org = $c->schema->resultset('PendingOrganisation')->find( $c->param('id') );
my $valid_org = $c->schema->resultset('Organisation')->create({
name => $pending_org->name,
street_name => $pending_org->street_name,
town => $pending_org->town,
postcode => $pending_org->postcode,
});
$c->copy_transactions_and_delete( $pending_org, $valid_org );
$c->flash( success => 'Validated Organisation' );
$c->redirect_to( '/admin/organisations/valid/' . $valid_org->id );
}
1;

View file

@ -17,21 +17,24 @@ sub index {
# POST
sub create {
my $c = shift;
my $validation = $c->validation;
$validation->required('token-name', 'trim')->like(qr/^[\w]*$/);
$validation->required('token', 'trim')->like(qr/^[\w]*$/)->not_in_resultset('name', $c->result_set);
my $token_name = $validation->param('token-name');
my $token_name = $validation->param('token');
my $token_rs = $c->result_set;
if ( $validation->has_error ) {
# Only one validator, fairly obvious whats broke
$c->flash( error => 'Token name not valid - Alphanumeric characters and Underscore only' );
} elsif ( $token_rs->find({ accounttokenname => $token_name }) ) {
$c->flash( error => 'Token Already Exists' );
my $check = shift @{ $c->validation->error('token') };
if ( $check eq 'required' ) {
$c->flash( error => 'Token name is required' );
} elsif ( $check eq 'like' ) {
$c->flash( error => 'Token name not valid - Alphanumeric characters and Underscore only' );
} elsif ( $check eq 'not_in_resultset' ) {
$c->flash( error => 'Token Already Exists' );
}
} else {
$c->flash( success => 'Token Created' );
$token_rs->create({ accounttokenname => $token_name });
$c->result_set->create({ name => $token_name });
}
$c->redirect_to( '/admin/tokens' );
}
@ -54,8 +57,8 @@ sub read {
sub update {
my $c = shift;
my $validation = $c->validation;
$validation->required('token-name', 'trim')->like(qr/^[\w]*$/);
$validation->required('token-used')->in( qw/ 0 1 / );
$validation->required('token', 'trim')->like(qr/^[\w]*$/);
$validation->required('used')->in( qw/ 0 1 / );
my $id = $c->param('id');
@ -65,8 +68,8 @@ sub update {
$c->redirect_to( '/admin/tokens/' . $id );
} elsif ( my $token = $c->result_set->find($id) ) {
$token->update({
accounttokenname => $validation->param('token-name'),
used => $validation->param('token-used'),
name => $validation->param('token'),
used => $validation->param('used'),
});
$c->flash( success => 'Token Updated' );
$c->redirect_to( '/admin/tokens/' . $id );

View file

@ -1,6 +1,23 @@
package Pear::LocalLoop::Controller::Api::Admin;
use Mojo::Base 'Mojolicious::Controller';
use Data::Dumper;
has error_messages => sub {
return {
target_organisation_id => {
required => { message => 'target_organisation_id is missing', status => 400 },
number => { message => 'target_organisation_id is not a number', status => 400 },
in_resultset => { message => 'target_organisation_id does not exist in the database', status => 400 },
},
pending_organisation_id => {
required => { message => 'pending_organisation_id is missing', status => 400 },
number => { message => 'pending_organisation_id is not a number', status => 400 },
in_resultset => { message => 'pending_organisation_id does not exist in the database', status => 400 },
},
postcode => {
postcode => { message => 'postcode is not a valid uk postcode', status => 400 },
},
};
};
sub auth {
my $c = shift;
@ -21,214 +38,69 @@ sub auth {
sub post_admin_approve {
my $c = shift;
my $self = $c;
my $user = $c->stash->{ api_user };
my $validation = $c->validation;
my $userId = $self->get_active_user_id();
if ( ! $self->is_admin($userId) ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'You are not an admin.',
$validation->input( $c->stash->{api_json} );
my $pending_org_rs = $c->schema->resultset('PendingOrganisation');
$validation->required('pending_organisation_id')->number->in_resultset('id', $pending_org_rs);
$validation->optional('name');
$validation->optional('street_name');
$validation->optional('town');
$validation->optional('postcode')->postcode;
return $c->api_validation_error if $validation->has_error;
my $pending_org = $pending_org_rs->find( $validation->param('pending_organisation_id') );
my $valid_org = $c->schema->resultset('Organisation')->create({
name => $validation->param('name') || $pending_org->name,
street_name => $validation->param('street_name') || $pending_org->street_name,
town => $validation->param('town') || $pending_org->town,
postcode => $validation->param('postcode') || $pending_org->postcode,
});
$c->copy_transactions_and_delete( $pending_org, $valid_org );
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Successfully Approved Organisation',
},
status => 403,); #Forbidden request
}
my $json = $self->req->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 $unvalidatedOrganisationId = $json->{unvalidatedOrganisationId};
if ( ! defined $unvalidatedOrganisationId ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'unvalidatedOrganisationId 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 => 'unvalidatedOrganisationId does not look like a number.',
},
status => 400,); #Malformed request
}
my ($id, $name, $fullAddress, $postcode) = $self->db->selectrow_array("SELECT PendingOrganisationId, Name, FullAddress, Postcode FROM PendingOrganisations WHERE PendingOrganisationId = ?", undef, ($unvalidatedOrganisationId));
#It does not exist.
if (! defined $id) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'the specified unvalidatedOrganisationId does not exist.',
},
status => 400,); #Malformed request
}
my $nameJson = $json->{name};
if (defined $nameJson) {
$name = $nameJson;
}
my $fullAddressJson = $json->{fullAddress};
if (defined $fullAddressJson) {
$fullAddress = $fullAddressJson;
}
my $postCodeJson = $json->{postCode};
if (defined $postCodeJson) {
$postcode = $postCodeJson;
}
#FIXME there may be race conditions here, so may get the wrong number, mutux is needed.
my $statementInsOrg = $self->db->prepare("INSERT INTO Organisations (Name, FullAddress, PostCode) VALUES (?, ?, ?)");
$statementInsOrg->execute($name, $fullAddress, $postcode);
my $organisationalId = $self->db->last_insert_id(undef,undef, "Organisations", "OrganisationalId");
#print "OrgId: " . $organisationalId . "\n";
my $statementSelectPendingTrans = $self->db->prepare("SELECT BuyerUserId_FK, ValueMicroCurrency, ProofImage, TimeDateSubmitted FROM PendingTransactions WHERE PendingSellerOrganisationId_FK = ?");
$statementSelectPendingTrans->execute($unvalidatedOrganisationId);
my $statementInsTrans = $self->db->prepare("INSERT INTO Transactions (BuyerUserId_FK, SellerOrganisationId_FK, ValueMicroCurrency, ProofImage, TimeDateSubmitted) VALUES (?, ?, ?, ?, ?)");
#Move all transactions from pending onto verified.
while (my ($buyerUserId, $value, $imgName, $timeDate) = $statementSelectPendingTrans->fetchrow_array()) {
$statementInsTrans->execute($buyerUserId, $organisationalId, $value, $imgName, $timeDate);
}
#Delete transactions first, so there is no dependancy when deleting the row from PendingOrganisations.
$self->db->prepare("DELETE FROM PendingTransactions WHERE PendingSellerOrganisationId_FK = ?")->execute($unvalidatedOrganisationId);
$self->db->prepare("DELETE FROM PendingOrganisations WHERE PendingOrganisationId = ?")->execute($unvalidatedOrganisationId);
$self->app->log->debug('Path Success: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->true,
validatedOrganisationId => $organisationalId,
},
status => 200,);
status => 200,
);
}
sub post_admin_merge {
my $self = shift;
my $c = shift;
my $userId = $self->get_active_user_id();
if ( ! $self->is_admin($userId) ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'You are not an admin.',
my $validation = $c->validation;
$validation->input( $c->stash->{api_json} );
my $pending_org_rs = $c->schema->resultset('PendingOrganisation');
$validation->required('pending_organisation_id')->number->in_resultset('id', $pending_org_rs);
my $valid_org_rs = $c->schema->resultset('Organisation');
$validation->required('target_organisation_id')->number->in_resultset('id', $valid_org_rs);
return $c->api_validation_error if $validation->has_error;
my $pending_org = $pending_org_rs->find( $validation->param('pending_organisation_id') );
my $target_org = $valid_org_rs->find( $validation->param('target_organisation_id') );
$c->copy_transactions_and_delete( $pending_org, $target_org );
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Successfully Merged Organisations',
},
status => 403,); #Forbidden request
}
my $json = $self->req->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 $unvalidatedOrganisationId = $json->{unvalidatedOrganisationId};
if ( ! defined $unvalidatedOrganisationId ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'unvalidatedOrganisationId 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 => 'unvalidatedOrganisationId does not look like a number.',
},
status => 400,); #Malformed request
}
my $validatedOrganisationId = $json->{validatedOrganisationId};
if ( ! defined $validatedOrganisationId ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'validatedOrganisationId is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($validatedOrganisationId)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'validatedOrganisationId does not look like a number.',
},
status => 400,); #Malformed request
}
#FIXME This requires mutual exclusion.
my $doesUnvalidatedIdNotExist = ($self->db->selectrow_array("SELECT COUNT(*) FROM PendingOrganisations WHERE PendingOrganisationId = ?", undef, ($unvalidatedOrganisationId)) == 0);
if ($doesUnvalidatedIdNotExist) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'unvalidatedOrganisationId does not exist in the database.',
},
status => 400,); #Malformed request
}
my $doesValidatedIdNotExist = ($self->db->selectrow_array("SELECT COUNT(*) FROM Organisations WHERE OrganisationalId = ?", undef, ($validatedOrganisationId)) == 0);
if ($doesValidatedIdNotExist) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'validatedOrganisationId does not exist in the database.',
},
status => 400,); #Malformed request
}
#FIXME there may be race conditions here, so may get the wrong number, mutux is needed.
my $statementSelectPendingTrans = $self->db->prepare("SELECT BuyerUserId_FK, ValueMicroCurrency, ProofImage, TimeDateSubmitted FROM PendingTransactions WHERE PendingSellerOrganisationId_FK = ?");
$statementSelectPendingTrans->execute($unvalidatedOrganisationId);
my $statementInsTrans = $self->db->prepare("INSERT INTO Transactions (BuyerUserId_FK, SellerOrganisationId_FK, ValueMicroCurrency, ProofImage, TimeDateSubmitted) VALUES (?, ?, ?, ?, ?)");
#Move all transactions from pending onto verified.
while (my ($buyerUserId, $value, $imgName, $timeDate) = $statementSelectPendingTrans->fetchrow_array()) {
$statementInsTrans->execute($buyerUserId, $validatedOrganisationId, $value, $imgName, $timeDate);
}
#Delete transactions first, so there is no dependancy when deleting the row from PendingOrganisations.
$self->db->prepare("DELETE FROM PendingTransactions WHERE PendingSellerOrganisationId_FK = ?")->execute($unvalidatedOrganisationId);
$self->db->prepare("DELETE FROM PendingOrganisations WHERE PendingOrganisationId = ?")->execute($unvalidatedOrganisationId);
$self->app->log->debug('Path Success: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->true,
},
status => 200,);
status => 200,
);
}
1;

View file

@ -42,7 +42,7 @@ sub auth {
my $session_key = $c->stash->{api_json}->{session_key};
if ( defined $session_key ) {
my $session_result = $c->schema->resultset('SessionToken')->find({ sessiontokenname => $session_key });
my $session_result = $c->schema->resultset('SessionToken')->find({ token => $session_key });
if ( defined $session_result ) {
$c->stash( api_user => $session_result->user );
@ -78,7 +78,7 @@ sub post_login {
if ( defined $user_result ) {
if ( $user_result->check_password($password) ) {
my $session_key = $c->generate_session( $user_result->userid );
my $session_key = $user_result->generate_session;
return $c->render( json => {
success => Mojo::JSON->true,
@ -101,7 +101,7 @@ sub post_logout {
my $session_key = $c->req->json( '/session_key' );
my $session_result = $c->schema->resultset('SessionToken')->find({ sessiontokenname => $session_key });
my $session_result = $c->schema->resultset('SessionToken')->find({ token => $session_key });
if ( defined $session_result ) {
$session_result->delete;

View file

@ -0,0 +1,12 @@
package Pear::LocalLoop::Controller::Api::Info;
use Mojo::Base 'Mojolicious::Controller';
sub get_ages {
my $c = shift;
my $ages = $c->schema->resultset('AgeRange');
$c->render( json => { ages => [ $ages->all ] } );
}
1;

View file

@ -8,10 +8,8 @@ has error_messages => sub {
required => { message => 'No token sent.', status => 400 },
in_resultset => { message => 'Token invalid or has been used.', status => 401 },
},
username => {
required => { message => 'No username sent or was blank.', status => 400 },
like => { message => 'Username can only be A-Z, a-z and 0-9 characters.', status => 400 },
not_in_resultset => { message => 'Username exists.', status => 403 },
name => {
required => { message => 'No name sent or was blank.', status => 400 },
},
email => {
required => { message => 'No email sent.', status => 400 },
@ -20,6 +18,7 @@ has error_messages => sub {
},
postcode => {
required => { message => 'No postcode sent.', status => 400 },
postcode => { message => 'Postcode is invalid', status => 400 },
},
password => {
required => { message => 'No password sent.', status => 400 },
@ -28,12 +27,16 @@ has error_messages => sub {
required => { message => 'No usertype sent.', status => 400 },
in => { message => '"usertype" is invalid.', status => 400 },
},
age => {
required => { message => 'No age sent.', status => 400 },
in_resultset => { message => 'Age range is invalid.', status => 400 },
age_range => {
required => { message => 'No age_range sent.', status => 400 },
number => { message => 'age_range is invalid', status => 400 },
in_resultset => { message => 'age_range is invalid.', status => 400 },
},
fulladdress => {
required => { message => 'No fulladdress sent.', status => 400 },
street_name => {
required => { message => 'No street_name sent.', status => 400 },
},
town => {
required => { message => 'No town sent.', status => 400 },
},
};
};
@ -42,87 +45,46 @@ sub post_register{
my $c = shift;
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} );
my $token_rs = $c->schema->resultset('AccountToken')->search_rs({used => 0});
$validation->required('token')->in_resultset('accounttokenname', $token_rs);
my $customer_rs = $c->schema->resultset('Customer');
$validation->required('username')->like(qr/^[A-Za-z0-9]+$/)->not_in_resultset('username', $customer_rs);
$validation->required('token')->in_resultset('name', $token_rs);
my $user_rs = $c->schema->resultset('User');
$validation->required('email')->email->not_in_resultset('email', $user_rs);
#TODO test to see if post code is valid.
$validation->required('postcode');
#TODO should we enforce password requirements.
$validation->required('password');
$validation->required('name');
$validation->required('postcode')->postcode;
$validation->required('usertype')->in('customer', 'organisation');
my $usertype = $validation->param('usertype') || '';
if ( $usertype eq 'customer' ) {
my $age_rs = $c->schema->resultset('AgeRange');
$validation->required('age')->in_resultset('agerangestring', $age_rs);
$validation->required('age_range')->number->in_resultset('id', $age_rs);
} elsif ( $usertype eq 'organisation' ) {
#TODO validation on the address. Or perhaps add the organisation to a "to be inspected" list then manually check them.
$validation->required('fulladdress');
$validation->required('street_name');
$validation->required('town');
}
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 $token = $validation->param('token');
my $username = $validation->param('username');
my $email = $validation->param('email');
my $postcode = $validation->param('postcode');
my $password = $validation->param('password');
return $c->api_validation_error if $validation->has_error;
if ($usertype eq 'customer'){
# TODO replace with actually using the value on the post request
my $ageForeignKey = $c->get_age_foreign_key( $validation->param('age') );
$c->schema->txn_do( sub {
$c->schema->resultset('AccountToken')->find({
accounttokenname => $token,
name => $validation->param('token'),
used => 0,
})->update({ used => 1 });
$c->schema->resultset('User')->create({
customer => {
username => $username,
agerange_fk => $ageForeignKey,
postcode => $postcode,
name => $validation->param('name'),
age_range_id => $validation->param('age_range'),
postcode => $validation->param('postcode'),
},
email => $email,
hashedpassword => $password,
joindate => DateTime->now,
email => $validation->param('email'),
password => $validation->param('password'),
});
});
@ -132,23 +94,26 @@ sub post_register{
$c->schema->txn_do( sub {
$c->schema->resultset('AccountToken')->find({
accounttokenname => $token,
name => $validation->param('token'),
used => 0,
})->update({ used => 1 });
$c->schema->resultset('User')->create({
organisation => {
name => $username,
fulladdress => $fullAddress,
postcode => $postcode,
name => $validation->param('name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
postcode => $validation->param('postcode'),
},
email => $email,
hashedpassword => $password,
joindate => DateTime->now,
email => $validation->param('email'),
password => $validation->param('password'),
});
});
}
return $c->render( json => { success => Mojo::JSON->true } );
return $c->render( json => {
success => Mojo::JSON->true,
message => 'Registered Successfully',
});
}
1;

View file

@ -67,12 +67,14 @@ has error_messages => sub {
organisation_name => {
required => { message => 'organisation_name is missing', status => 400 },
},
search_name => {
required => { message => 'search_name is missing', status => 400 },
},
};
};
sub post_upload {
my $c = shift;
my $self = $c;
my $user = $c->stash->{api_user};
@ -91,171 +93,114 @@ sub post_upload {
my $type = $validation->param('transaction_type');
my $organisation;
if ( $type == 1 ) {
# Validated Organisation
my $valid_org_rs = $c->schema->resultset('Organisation');
$validation->required('organisation_id')->number->in_resultset( 'organisationalid', $valid_org_rs );
$validation->required('organisation_id')->number->in_resultset( 'id', $valid_org_rs );
return $c->api_validation_error if $validation->has_error;
$organisation = $valid_org_rs->find( $validation->param('organisation_id') );
} elsif ( $type == 2 ) {
# Unvalidated Organisation
my $valid_org_rs = $c->schema->resultset('PendingOrganisation')->search({ usersubmitted_fk => $user->id });
$validation->required('organisation_id')->number->in_resultset( 'pendingorganisationid', $valid_org_rs );
my $valid_org_rs = $c->schema->resultset('PendingOrganisation')->search({ submitted_by_id => $user->id });
$validation->required('organisation_id')->number->in_resultset( 'id', $valid_org_rs );
return $c->api_validation_error if $validation->has_error;
$organisation = $valid_org_rs->find( $validation->param('organisation_id') );
} elsif ( $type == 3 ) {
# Unknown Organisation
$validation->required('organisation_name');
$validation->optional('street_name');
$validation->optional('town');
$validation->optional('postcode')->postcode;
}
return $c->api_validation_error if $validation->has_error;
return $c->api_validation_error if $validation->has_error;
$organisation = $c->schema->resultset('PendingOrganisation')->create({
submitted_by => $user,
submitted_at => DateTime->now,
name => $validation->param('organisation_name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
postcode => $validation->param('postcode'),
});
}
my $transaction_value = $validation->param('transaction_value');
my $upload = $validation->param('file');
my $file = $c->store_file_from_upload( $upload );
my $file = $validation->param('file');
my $ext = '.jpg';
my $uuid = Data::UUID->new->create_str;
my $filename = $uuid . $ext;
if ( $type == 1 ) {
# Validated organisation
$c->schema->resultset('Transaction')->create({
buyeruserid_fk => $user->id,
sellerorganisationid_fk => $validation->param('organisation_id'),
valuemicrocurrency => $transaction_value,
proofimage => $filename,
timedatesubmitted => DateTime->now,
});
$file->move_to('images/' . $filename);
} elsif ( $type == 2 ) {
# Unvalidated Organisation
$c->schema->resultset('PendingTransaction')->create({
buyeruserid_fk => $user->id,
pendingsellerorganisationid_fk => $validation->param('organisation_id'),
valuemicrocurrency => $transaction_value,
proofimage => $filename,
timedatesubmitted => DateTime->now,
});
$file->move_to('images/' . $filename);
} elsif ( $type == 3 ) {
my $organisation_name = $validation->param('organisation_name');
my $street_name = $validation->param('street_name');
my $town = $validation->param('town');
my $postcode = $validation->param('postcode');
my $fullAddress = "";
if ( defined $street_name && ! ($street_name =~ m/^\s*$/) ){
$fullAddress = $street_name;
$organisation->create_related(
'transactions',
{
buyer => $user,
value => $transaction_value,
proof_image => $file,
}
);
if ( defined $town && ! ($town =~ m/^\s*$/) ){
if ($fullAddress eq ""){
$fullAddress = $town;
}
else{
$fullAddress = $fullAddress . ", " . $town;
}
}
my $pending_org = $c->schema->resultset('PendingOrganisation')->create({
usersubmitted_fk => $user->id,
timedatesubmitted => DateTime->now,
name => $organisation_name,
fulladdress => $fullAddress,
postcode => $postcode,
});
$c->schema->resultset('PendingTransaction')->create({
buyeruserid_fk => $user->id,
pendingsellerorganisationid_fk => $pending_org->pendingorganisationid,
valuemicrocurrency => $transaction_value,
proofimage => $filename,
timedatesubmitted => DateTime->now,
});
$file->move_to('images/' . $filename);
}
return $self->render( json => {
return $c->render( json => {
success => Mojo::JSON->true,
message => 'Upload Successful',
});
}
#TODO this should limit the number of responses returned, when location is implemented that would be the main way of filtering.
# TODO Limit search results, possibly paginate them?
# TODO Search by location as well
sub post_search {
my $self = shift;
my $userId = $self->get_active_user_id();
my $c = shift;
my $self = $c;
my $json = $self->req->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;
my $searchName = $json->{searchName};
if ( ! defined $searchName ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'searchName is missing.',
},
status => 400,); #Malformed request
}
#Is blank
elsif ( $searchName =~ m/^\s*$/) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'searchName is blank.',
},
status => 400,); #Malformed request
}
$validation->input( $c->stash->{api_json} );
#Currently ignored
#TODO implement further.
my $searchLocation = $json->{searchLocation};
$validation->required('search_name');
my @validatedOrgs = ();
{
my $statementValidated = $self->db->prepare("SELECT OrganisationalId, Name, FullAddress, PostCode FROM Organisations WHERE UPPER( Name ) LIKE ?");
$statementValidated->execute('%'. uc $searchName.'%');
return $c->api_validation_error if $validation->has_error;
while (my ($id, $name, $address, $postcode) = $statementValidated->fetchrow_array()) {
push(@validatedOrgs, $self->create_hash($id,$name,$address,$postcode));
}
}
my $search_name = $validation->param('search_name');
$self->app->log->debug( "Orgs: " . Dumper @validatedOrgs );
my $valid_orgs_rs = $c->schema->resultset('Organisation')->search(
{ 'LOWER(name)' => { -like => '%' . lc $search_name . '%' } },
);
my @unvalidatedOrgs = ();
{
my $statementUnvalidated = $self->db->prepare("SELECT PendingOrganisationId, Name, FullAddress, Postcode FROM PendingOrganisations WHERE UPPER( Name ) LIKE ? AND UserSubmitted_FK = ?");
$statementUnvalidated->execute('%'. uc $searchName.'%', $userId);
my $pending_orgs_rs = $c->stash->{api_user}->pending_organisations->search(
{ 'LOWER(name)' => { -like => '%' . lc $search_name . '%' } },
);
my @valid_orgs = (
map {{
id => $_->id,
name => $_->name,
street_name => $_->street_name,
town => $_->town,
postcode => $_->postcode,
}} $valid_orgs_rs->all
);
my @pending_orgs = (
map {{
id => $_->id,
name => $_->name,
street_name => $_->street_name,
town => $_->town,
postcode => $_->postcode,
}} $pending_orgs_rs->all
);
while (my ($id, $name, $fullAddress, $postcode) = $statementUnvalidated->fetchrow_array()) {
push(@unvalidatedOrgs, $self->create_hash($id, $name, $fullAddress, $postcode));
}
}
$self->app->log->debug( "Non Validated Orgs: " . Dumper @unvalidatedOrgs );
$self->app->log->debug('Path Success: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->true,
unvalidated => \@unvalidatedOrgs,
validated => \@validatedOrgs,
},
status => 200,);
validated => \@valid_orgs,
unvalidated => \@pending_orgs,
});
}
1;

View file

@ -1,341 +1,29 @@
package Pear::LocalLoop::Controller::Api::User;
use Mojo::Base 'Mojolicious::Controller';
use Data::Dumper;
use Mojo::JSON;
use DateTime;
use DateTime::Duration;
use TryCatch;
sub post_user_history {
my $self = shift;
my $userId = $self->get_active_user_id();
my $json = $self->req->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.',
has error_messages => sub {
return {
day => {
is_iso_datetime => { message => 'Invalid ISO8601 Datetime', status => 400 },
},
status => 400,); #Malformed request
}
};
};
my $retrieveType = $json->{retrieveType};
if ( ! defined $retrieveType ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'retrieveType is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($retrieveType)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'retrieveType does not look like a number.',
},
status => 400,); #Malformed request
}
sub post_day {
my $c = shift;
#Date time.
my $startDateTime;
my $endDateTime;
my $validation = $c->validation;
#One day
if ($retrieveType == 1){
my $startDayNumber = $json->{dayNumber};
if ( ! defined $startDayNumber ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'dayNumber is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($startDayNumber)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'dayNumber does not look like a number.',
},
status => 400,); #Malformed request
}
$validation->input( $c->stash->{api_json} );
my $startMonthNumber = $json->{monthNumber};
if ( ! defined $startMonthNumber ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'monthNumber is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($startMonthNumber)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'monthNumber does not look like a number.',
},
status => 400,); #Malformed request
}
$validation->optional('day')->is_iso_datetime;
my $startYear = $json->{year};
if ( ! defined $startYear ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'year is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($startYear)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'year does not look like a number.',
},
status => 400,); #Malformed request
}
return $c->api_validation_error if $validation->has_error;
try
{
$startDateTime = DateTime->new(
year => $startYear,
month => $startMonthNumber,
day => $startDayNumber,
);
}
catch
{
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'date is invalid.',
},
status => 400,); #Malformed request
};
$endDateTime = $startDateTime->clone();
}
elsif ($retrieveType == 2){
my $startDayNumber = $json->{startDayNumber};
if ( ! defined $startDayNumber ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'startDayNumber is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($startDayNumber)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'startDayNumber does not look like a number.',
},
status => 400,); #Malformed request
}
my $startMonthNumber = $json->{startMonthNumber};
if ( ! defined $startMonthNumber ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'startMonthNumber is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($startMonthNumber)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'startMonthNumber does not look like a number.',
},
status => 400,); #Malformed request
}
my $startYear = $json->{startYear};
if ( ! defined $startYear ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'startYear is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($startYear)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'startYear does not look like a number.',
},
status => 400,); #Malformed request
}
try
{
$startDateTime = DateTime->new(
year => $startYear,
month => $startMonthNumber,
day => $startDayNumber,
);
}
catch
{
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'start date is invalid.',
},
status => 400,); #Malformed request
};
my $endDayNumber = $json->{endDayNumber};
if ( ! defined $endDayNumber ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'endDayNumber is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($endDayNumber)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'endDayNumber does not look like a number.',
},
status => 400,); #Malformed request
}
my $endMonthNumber = $json->{endMonthNumber};
if ( ! defined $endMonthNumber ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'endMonthNumber is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($endMonthNumber)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'endMonthNumber does not look like a number.',
},
status => 400,); #Malformed request
}
my $endYear = $json->{endYear};
if ( ! defined $endYear ) {
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'endYear is missing.',
},
status => 400,); #Malformed request
}
elsif (! Scalar::Util::looks_like_number($endYear)){
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'endYear does not look like a number.',
},
status => 400,); #Malformed request
}
try
{
$endDateTime = DateTime->new(
year => $endYear,
month => $endMonthNumber,
day => $endDayNumber,
);
}
catch
{
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'end date is invalid.',
},
status => 400,); #Malformed request
};
}
else{
$self->app->log->debug('Path Error: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
success => Mojo::JSON->false,
message => 'retrieveType can only be 1 or 2.',
},
status => 400,); #Malformed request
}
$endDateTime->add(days => 1);
my $startEpoch = $startDateTime->epoch();
my $endEpoch = $endDateTime->epoch();
$self->app->log->debug( "startEpoch: " . Dumper($startEpoch));
$self->app->log->debug( "endEpoch: " . Dumper($endEpoch));
my $dataSpend = {};
my $statementSelectPendingTrans = $self->db->prepare("SELECT TimeDateSubmitted, ValueMicroCurrency FROM Transactions WHERE BuyerUserId_FK = ? AND ? <= TimeDateSubmitted AND TimeDateSubmitted < ? ORDER BY TimeDateSubmitted ASC");
$statementSelectPendingTrans->execute($userId, $startEpoch, $endEpoch);
#We assume "microCurrencySum" is always more than 0 due to database and input constraints in "/upload".
sub add_value_to_hash {
my ($self, $microCurrencySum, $dateTimePreviousState, $dataSpend) = @_;
#if ($microCurrencySum != 0) {
my $year = $dateTimePreviousState->year();
my $month = $dateTimePreviousState->month();
my $day = $dateTimePreviousState->day();
$dataSpend->{$year}{$month}{$day} = $microCurrencySum;
#}
}
if (my ($timeDateSubmitted, $valueMicroCurrency) = $statementSelectPendingTrans->fetchrow_array()) {
my $dateTimeTruncator = DateTime->from_epoch(epoch => $timeDateSubmitted);
$dateTimeTruncator->truncate( to => 'day');
#Set to 0 then add the current value like the else block.
my $microCurrencySum = $valueMicroCurrency;
#Set to the first row time
my $dateTimePreviousState = $dateTimeTruncator;
while (my ($timeDateSubmitted, $valueMicroCurrency) = $statementSelectPendingTrans->fetchrow_array()) {
$dateTimeTruncator = DateTime->from_epoch(epoch => $timeDateSubmitted);
$dateTimeTruncator->truncate( to => 'day');
if (DateTime->compare($dateTimePreviousState, $dateTimeTruncator) != 0 ){
add_value_to_hash($self, $microCurrencySum, $dateTimePreviousState, $dataSpend);
$microCurrencySum = $valueMicroCurrency; #Reset to 0 then add the current value like the else block.
$dateTimePreviousState = $dateTimeTruncator;
}
else{
$microCurrencySum += $valueMicroCurrency; #Same day to keep adding the values.
}
}
add_value_to_hash($self, $microCurrencySum, $dateTimePreviousState, $dataSpend);
}
$self->app->log->debug('Path Success: file:' . __FILE__ . ', line: ' . __LINE__);
return $self->render( json => {
microCurencySpent => $dataSpend,
$c->render( json => {
success => Mojo::JSON->true,
},
status => 200,);
});
}
1;

View file

@ -0,0 +1,11 @@
package Pear::LocalLoop::Controller::Portal;
use Mojo::Base 'Mojolicious::Controller';
sub under {
my $c = shift;
$c->stash( api_user => $c->current_user );
return 1;
}
1;

View file

@ -35,10 +35,10 @@ sub register {
$validation->required('email')->email->not_in_resultset('email', $user_rs);
my $token_rs = $c->schema->resultset('AccountToken')->search_rs({used => 0});
$validation->required('token')->in_resultset('accounttokenname', $token_rs);
$validation->required('token')->in_resultset('name', $token_rs);
my $age_rs = $c->schema->resultset('AgeRange');
$validation->required('agerange')->in_resultset('agerangeid', $age_rs);
$validation->required('agerange')->in_resultset('id', $age_rs);
my @error_messages;
if ( $validation->has_error ) {
@ -47,12 +47,11 @@ sub register {
} else {
my $new_user = $c->schema->resultset('User')->find_or_new({
email => $validation->param('email'),
hashedpassword => $validation->param('password'),
joindate => DateTime->now(),
password => $validation->param('password'),
customer => {
username => $validation->param('name'),
postcode => $validation->param('postcode'),
agerange_fk => $validation->param('agerange'),
age_range_id => $validation->param('agerange'),
},
});
if ( $new_user->in_storage ) {

View file

@ -4,7 +4,8 @@ use Mojo::Base 'Mojolicious::Plugin';
use Email::Valid;
use Geo::UK::Postcode;
use Scalar::Util qw/ looks_like_number /;
use File::Basename;
use File::Basename qw/ fileparse /;
use DateTime::Format::Strptime;
sub register {
my ( $plugin, $app, $conf ) = @_;
@ -45,6 +46,12 @@ sub register {
$extension =~ s/^\.//;
return $app->types->type($extension) eq $filetype ? undef : 1;
});
$app->validator->add_check( is_iso_datetime => sub {
my ( $validation, $name, $value ) = @_;
$value = $app->datetime_formatter->parse_datetime( $value );
return defined $value ? undef : 1;
});
}
1;

View file

@ -1,9 +1,6 @@
use utf8;
package Pear::LocalLoop::Schema;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
use strict;
use warnings;
@ -11,10 +8,4 @@ use base 'DBIx::Class::Schema';
__PACKAGE__->load_namespaces;
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JNwB+HEKyNyE5ZP1Br1pog
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,98 +1,23 @@
use utf8;
package Pear::LocalLoop::Schema::Result::AccountToken;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::AccountToken
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<AccountTokens>
=cut
__PACKAGE__->table("AccountTokens");
=head1 ACCESSORS
=head2 accounttokenid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 accounttokenname
data_type: 'text'
is_nullable: 0
=head2 used
data_type: 'integer'
default_value: 0
is_nullable: 0
=cut
__PACKAGE__->table("account_tokens");
__PACKAGE__->add_columns(
"accounttokenid",
"id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"accounttokenname",
"name",
{ data_type => "text", is_nullable => 0 },
"used",
{ data_type => "integer", default_value => 0, is_nullable => 0 },
);
=head1 PRIMARY KEY
__PACKAGE__->set_primary_key("id");
=over 4
__PACKAGE__->add_unique_constraint(["name"]);
=item * L</accounttokenid>
=back
=cut
__PACKAGE__->set_primary_key("accounttokenid");
=head1 UNIQUE CONSTRAINTS
=head2 C<accounttokenname_unique>
=over 4
=item * L</accounttokenname>
=back
=cut
__PACKAGE__->add_unique_constraint("accounttokenname_unique", ["accounttokenname"]);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:MeN6dMZY0drrWk+En7E5Ag
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,92 +1,28 @@
use utf8;
package Pear::LocalLoop::Schema::Result::Administrator;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::Administrator
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<Administrators>
=cut
__PACKAGE__->table("Administrators");
=head1 ACCESSORS
=head2 userid
data_type: 'integer'
is_auto_increment: 1
is_foreign_key: 1
is_nullable: 0
=cut
__PACKAGE__->table("administrators");
__PACKAGE__->add_columns(
"userid",
"user_id",
{
data_type => "integer",
is_auto_increment => 1,
is_foreign_key => 1,
is_nullable => 0,
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
);
=head1 PRIMARY KEY
=over 4
=item * L</userid>
=back
=cut
__PACKAGE__->set_primary_key("userid");
=head1 RELATIONS
=head2 userid
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->set_primary_key("user_id");
__PACKAGE__->belongs_to(
"userid",
"user",
"Pear::LocalLoop::Schema::Result::User",
{ userid => "userid" },
{ id => "user_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:YLzlp1ru+1id/O4bTJGqbw
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,107 +1,37 @@
use utf8;
package Pear::LocalLoop::Schema::Result::AgeRange;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::AgeRange
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<AgeRanges>
=cut
__PACKAGE__->table("AgeRanges");
=head1 ACCESSORS
=head2 agerangeid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 agerangestring
data_type: 'text'
is_nullable: 0
=cut
__PACKAGE__->table("age_ranges");
__PACKAGE__->add_columns(
"agerangeid",
"id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"agerangestring",
"string",
{ data_type => "text", is_nullable => 0 },
);
=head1 PRIMARY KEY
__PACKAGE__->set_primary_key("id");
=over 4
=item * L</agerangeid>
=back
=cut
__PACKAGE__->set_primary_key("agerangeid");
=head1 UNIQUE CONSTRAINTS
=head2 C<agerangestring_unique>
=over 4
=item * L</agerangestring>
=back
=cut
__PACKAGE__->add_unique_constraint("agerangestring_unique", ["agerangestring"]);
=head1 RELATIONS
=head2 customers
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::Customer>
=cut
__PACKAGE__->add_unique_constraint(["string"]);
__PACKAGE__->has_many(
"customers",
"Pear::LocalLoop::Schema::Result::Customer",
{ "foreign.agerange_fk" => "self.agerangeid" },
{ "foreign.age_range_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
sub TO_JSON {
my $self = shift;
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:4zGNm0RlwptF9hlj9oErVA
return {
id => $self->id,
string => $self->string,
};
}
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,137 +1,49 @@
use utf8;
package Pear::LocalLoop::Schema::Result::Customer;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::Customer
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<Customers>
=cut
__PACKAGE__->table("Customers");
=head1 ACCESSORS
=head2 customerid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 username
data_type: 'text'
is_nullable: 0
=head2 agerange_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 postcode
data_type: 'text'
is_nullable: 0
=cut
__PACKAGE__->table("customers");
__PACKAGE__->add_columns(
"customerid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"username",
{ data_type => "text", is_nullable => 0 },
"agerange_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"postcode",
{ data_type => "text", is_nullable => 0 },
"id" => {
data_type => "integer",
is_auto_increment => 1,
is_nullable => 0,
},
"name" => {
data_type => "varchar",
size => 255,
is_nullable => 0,
},
"age_range_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
"postcode" => {
data_type => "varchar",
size => 16,
is_nullable => 0,
},
);
=head1 PRIMARY KEY
=over 4
=item * L</customerid>
=back
=cut
__PACKAGE__->set_primary_key("customerid");
=head1 UNIQUE CONSTRAINTS
=head2 C<username_unique>
=over 4
=item * L</username>
=back
=cut
__PACKAGE__->add_unique_constraint("username_unique", ["username"]);
=head1 RELATIONS
=head2 agerange_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::AgeRange>
=cut
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"agerange_fk",
"age_range",
"Pear::LocalLoop::Schema::Result::AgeRange",
{ agerangeid => "agerange_fk" },
{ id => "age_range_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
=head2 user
Type: might_have
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->might_have(
"user",
"Pear::LocalLoop::Schema::Result::User",
{ "foreign.customerid_fk" => "self.customerid" },
{ "foreign.customer_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ocoCGZYvw9O9wxzr14okiQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,122 +1,55 @@
use utf8;
package Pear::LocalLoop::Schema::Result::Organisation;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::Organisation
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<Organisations>
=cut
__PACKAGE__->table("Organisations");
=head1 ACCESSORS
=head2 organisationalid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 name
data_type: 'text'
is_nullable: 0
=head2 fulladdress
data_type: 'text'
is_nullable: 0
=head2 postcode
data_type: 'text'
is_nullable: 0
=cut
__PACKAGE__->table("organisations");
__PACKAGE__->add_columns(
"organisationalid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"name",
{ data_type => "text", is_nullable => 0 },
"fulladdress",
{ data_type => "text", is_nullable => 0 },
"postcode",
{ data_type => "text", is_nullable => 0 },
id => {
data_type => 'integer',
is_auto_increment => 1,
is_nullable => 0,
},
name => {
data_type => 'varchar',
size => 255,
is_nullable => 0,
},
street_name => {
data_type => 'text',
is_nullable => 1,
},
town => {
data_type => 'varchar',
size => 255,
is_nullable => 0,
},
postcode => {
data_type => 'varchar',
size => 16,
is_nullable => 1,
},
);
=head1 PRIMARY KEY
=over 4
=item * L</organisationalid>
=back
=cut
__PACKAGE__->set_primary_key("organisationalid");
=head1 RELATIONS
=head2 transactions
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::Transaction>
=cut
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(
"transactions",
"Pear::LocalLoop::Schema::Result::Transaction",
{ "foreign.sellerorganisationid_fk" => "self.organisationalid" },
{ "foreign.seller_id" => 'self.id' },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 user
Type: might_have
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->might_have(
"user",
"Pear::LocalLoop::Schema::Result::User",
{ "foreign.organisationalid_fk" => "self.organisationalid" },
{ "foreign.organisation_id" => 'self.id' },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:p9FzM/H5YQbo2d0lN/DfCg
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,139 +1,70 @@
use utf8;
package Pear::LocalLoop::Schema::Result::PendingOrganisation;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::PendingOrganisation
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
__PACKAGE__->load_components( qw/
InflateColumn::DateTime
TimeStamp
/);
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<PendingOrganisations>
=cut
__PACKAGE__->table("PendingOrganisations");
=head1 ACCESSORS
=head2 pendingorganisationid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 usersubmitted_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 timedatesubmitted
data_type: 'integer'
is_nullable: 0
=head2 name
data_type: 'text'
is_nullable: 0
=head2 fulladdress
data_type: 'text'
is_nullable: 1
=head2 postcode
data_type: 'text'
is_nullable: 1
=cut
__PACKAGE__->table("pending_organisations");
__PACKAGE__->add_columns(
"pendingorganisationid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"usersubmitted_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"timedatesubmitted",
{ data_type => "datetime", is_nullable => 0 },
"name",
{ data_type => "text", is_nullable => 0 },
"fulladdress",
{ data_type => "text", is_nullable => 1 },
"postcode",
{ data_type => "text", is_nullable => 1 },
id => {
data_type => 'integer',
is_auto_increment => 1,
is_nullable => 0,
},
name => {
data_type => 'varchar',
size => 255,
is_nullable => 0,
},
street_name => {
data_type => 'text',
is_nullable => 1,
},
town => {
data_type => 'varchar',
size => 255,
is_nullable => 0,
},
postcode => {
data_type => 'varchar',
size => 16,
is_nullable => 1,
},
submitted_by_id => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
submitted_at => {
data_type => "datetime",
is_nullable => 0,
set_on_create => 1,
},
);
=head1 PRIMARY KEY
=over 4
=item * L</pendingorganisationid>
=back
=cut
__PACKAGE__->set_primary_key("pendingorganisationid");
=head1 RELATIONS
=head2 pending_transactions
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::PendingTransaction>
=cut
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(
"pending_transactions",
"transactions",
"Pear::LocalLoop::Schema::Result::PendingTransaction",
{
"foreign.pendingsellerorganisationid_fk" => "self.pendingorganisationid",
"foreign.seller_id" => "self.id",
},
{ cascade_copy => 0, cascade_delete => 0 },
{ cascade_copy => 0, cascade_delete => 1 },
);
=head2 usersubmitted_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->belongs_to(
"usersubmitted_fk",
"submitted_by",
"Pear::LocalLoop::Schema::Result::User",
{ userid => "usersubmitted_fk" },
{ id => "submitted_by_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ekEOt+ESCwQxrqqlMurehA
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,152 +1,63 @@
use utf8;
package Pear::LocalLoop::Schema::Result::PendingTransaction;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::PendingTransaction
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
__PACKAGE__->load_components( qw/
InflateColumn::DateTime
TimeStamp
/);
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<PendingTransactions>
=cut
__PACKAGE__->table("PendingTransactions");
=head1 ACCESSORS
=head2 pendingtransactionid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 buyeruserid_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 pendingsellerorganisationid_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 valuemicrocurrency
data_type: 'integer'
is_nullable: 0
=head2 proofimage
data_type: 'text'
is_nullable: 0
=head2 timedatesubmitted
data_type: 'integer'
is_nullable: 0
=cut
__PACKAGE__->table("pending_transactions");
__PACKAGE__->add_columns(
"pendingtransactionid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"buyeruserid_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"pendingsellerorganisationid_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"valuemicrocurrency",
{ data_type => "integer", is_nullable => 0 },
"proofimage",
{ data_type => "text", is_nullable => 0 },
"timedatesubmitted",
{ data_type => "datetime", is_nullable => 0 },
"id" => {
data_type => "integer",
is_auto_increment => 1,
is_nullable => 0,
},
"buyer_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
"seller_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
"value" => {
data_type => "decimal",
size => [ 16, 2 ],
is_nullable => 0,
},
"proof_image" => {
data_type => "text",
is_nullable => 0,
},
"submitted_at" => {
data_type => "datetime",
is_nullable => 0,
set_on_create => 1,
},
);
=head1 PRIMARY KEY
=over 4
=item * L</pendingtransactionid>
=back
=cut
__PACKAGE__->set_primary_key("pendingtransactionid");
=head1 UNIQUE CONSTRAINTS
=head2 C<proofimage_unique>
=over 4
=item * L</proofimage>
=back
=cut
__PACKAGE__->add_unique_constraint("proofimage_unique", ["proofimage"]);
=head1 RELATIONS
=head2 buyeruserid_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"buyeruserid_fk",
"buyer",
"Pear::LocalLoop::Schema::Result::User",
{ userid => "buyeruserid_fk" },
{ id => "buyer_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
=head2 pendingsellerorganisationid_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::PendingOrganisation>
=cut
__PACKAGE__->belongs_to(
"pendingsellerorganisationid_fk",
"seller",
"Pear::LocalLoop::Schema::Result::PendingOrganisation",
{ pendingorganisationid => "pendingsellerorganisationid_fk" },
{ id => "seller_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zwtxzfW5uB4FNA6mKdFOvg
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,122 +1,39 @@
use utf8;
package Pear::LocalLoop::Schema::Result::SessionToken;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::SessionToken
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<SessionTokens>
=cut
__PACKAGE__->table("SessionTokens");
=head1 ACCESSORS
=head2 sessiontokenid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 sessiontokenname
data_type: 'text'
is_nullable: 0
=head2 useridassignedto_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 expiredatetime
data_type: 'integer'
is_nullable: 0
=cut
__PACKAGE__->table("session_tokens");
__PACKAGE__->add_columns(
"sessiontokenid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"sessiontokenname",
{ data_type => "text", is_nullable => 0 },
"useridassignedto_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"expiredatetime",
{ data_type => "datetime", is_nullable => 0 },
"id" => {
data_type => "integer",
is_auto_increment => 1,
is_nullable => 0,
},
"token" => {
data_type => "varchar",
size => 255,
is_nullable => 0,
},
"user_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
);
=head1 PRIMARY KEY
__PACKAGE__->set_primary_key("id");
=over 4
=item * L</sessiontokenid>
=back
=cut
__PACKAGE__->set_primary_key("sessiontokenid");
=head1 UNIQUE CONSTRAINTS
=head2 C<sessiontokenname_unique>
=over 4
=item * L</sessiontokenname>
=back
=cut
__PACKAGE__->add_unique_constraint("sessiontokenname_unique", ["sessiontokenname"]);
=head1 RELATIONS
=head2 useridassignedto_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->add_unique_constraint(["token"]);
__PACKAGE__->belongs_to(
"user",
"Pear::LocalLoop::Schema::Result::User",
{ userid => "useridassignedto_fk" },
{ id => "user_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/mNAPeSmfsDSIpey+eUucg
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,152 +1,63 @@
use utf8;
package Pear::LocalLoop::Schema::Result::Transaction;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::Transaction
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
__PACKAGE__->load_components(qw/
InflateColumn::DateTime
TimeStamp
/);
=over 4
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime");
=head1 TABLE: C<Transactions>
=cut
__PACKAGE__->table("Transactions");
=head1 ACCESSORS
=head2 transactionid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 buyeruserid_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 sellerorganisationid_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 valuemicrocurrency
data_type: 'integer'
is_nullable: 0
=head2 proofimage
data_type: 'text'
is_nullable: 0
=head2 timedatesubmitted
data_type: 'integer'
is_nullable: 0
=cut
__PACKAGE__->table("transactions");
__PACKAGE__->add_columns(
"transactionid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"buyeruserid_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"sellerorganisationid_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"valuemicrocurrency",
{ data_type => "integer", is_nullable => 0 },
"proofimage",
{ data_type => "text", is_nullable => 0 },
"timedatesubmitted",
{ data_type => "datetime", is_nullable => 0 },
"id" => {
data_type => "integer",
is_auto_increment => 1,
is_nullable => 0,
},
"buyer_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
"seller_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 0,
},
"value" => {
data_type => "decimal",
size => [ 16, 2 ],
is_nullable => 0,
},
"proof_image" => {
data_type => "text",
is_nullable => 0,
},
"submitted_at" => {
data_type => "datetime",
is_nullable => 0,
set_on_create => 1,
},
);
=head1 PRIMARY KEY
=over 4
=item * L</transactionid>
=back
=cut
__PACKAGE__->set_primary_key("transactionid");
=head1 UNIQUE CONSTRAINTS
=head2 C<proofimage_unique>
=over 4
=item * L</proofimage>
=back
=cut
__PACKAGE__->add_unique_constraint("proofimage_unique", ["proofimage"]);
=head1 RELATIONS
=head2 buyeruserid_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::User>
=cut
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"buyeruserid_fk",
"buyer",
"Pear::LocalLoop::Schema::Result::User",
{ userid => "buyeruserid_fk" },
{ id => "buyer_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
=head2 sellerorganisationid_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::Organisation>
=cut
__PACKAGE__->belongs_to(
"sellerorganisationid_fk",
"seller",
"Pear::LocalLoop::Schema::Result::Organisation",
{ organisationalid => "sellerorganisationid_fk" },
{ id => "seller_id" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CfPoE2egoSD1tKo7fYjZdg
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,88 +1,45 @@
use utf8;
package Pear::LocalLoop::Schema::Result::User;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Pear::LocalLoop::Schema::Result::User
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
use Data::UUID;
=over 4
__PACKAGE__->load_components( qw/
InflateColumn::DateTime
PassphraseColumn
TimeStamp
/);
=item * L<DBIx::Class::InflateColumn::DateTime>
=back
=cut
__PACKAGE__->load_components("InflateColumn::DateTime", "PassphraseColumn");
=head1 TABLE: C<Users>
=cut
__PACKAGE__->table("Users");
=head1 ACCESSORS
=head2 userid
data_type: 'integer'
is_auto_increment: 1
is_nullable: 0
=head2 customerid_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 1
=head2 organisationalid_fk
data_type: 'integer'
is_foreign_key: 1
is_nullable: 1
=head2 email
data_type: 'text'
is_nullable: 0
=head2 joindate
data_type: 'integer'
is_nullable: 0
=head2 hashedpassword
data_type: 'text'
is_nullable: 0
=cut
__PACKAGE__->table("users");
__PACKAGE__->add_columns(
"userid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"customerid_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
"organisationalid_fk",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
"email",
{ data_type => "text", is_nullable => 0 },
"joindate",
{ data_type => "datetime", is_nullable => 0 },
"hashedpassword",
{
"id" => {
data_type => "integer",
is_auto_increment => 1,
is_nullable => 0,
},
"customer_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 1,
},
"organisation_id" => {
data_type => "integer",
is_foreign_key => 1,
is_nullable => 1,
},
"email" => {
data_type => "text",
is_nullable => 0,
},
"join_date" => {
data_type => "datetime",
set_on_create => 1,
},
"password" => {
data_type => "varchar",
is_nullable => 0,
size => 100,
@ -96,85 +53,25 @@ __PACKAGE__->add_columns(
},
);
=head1 PRIMARY KEY
__PACKAGE__->set_primary_key("id");
=over 4
__PACKAGE__->add_unique_constraint(["customer_id"]);
=item * L</userid>
__PACKAGE__->add_unique_constraint(["email"]);
=back
=cut
__PACKAGE__->set_primary_key("userid");
=head1 UNIQUE CONSTRAINTS
=head2 C<customerid_fk_unique>
=over 4
=item * L</customerid_fk>
=back
=cut
__PACKAGE__->add_unique_constraint("customerid_fk_unique", ["customerid_fk"]);
=head2 C<email_unique>
=over 4
=item * L</email>
=back
=cut
__PACKAGE__->add_unique_constraint("email_unique", ["email"]);
=head2 C<organisationalid_fk_unique>
=over 4
=item * L</organisationalid_fk>
=back
=cut
__PACKAGE__->add_unique_constraint("organisationalid_fk_unique", ["organisationalid_fk"]);
=head1 RELATIONS
=head2 administrator
Type: might_have
Related object: L<Pear::LocalLoop::Schema::Result::Administrator>
=cut
__PACKAGE__->add_unique_constraint(["organisation_id"]);
__PACKAGE__->might_have(
"administrator",
"Pear::LocalLoop::Schema::Result::Administrator",
{ "foreign.userid" => "self.userid" },
{ "foreign.user_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 customerid_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::Customer>
=cut
__PACKAGE__->belongs_to(
"customer",
"Pear::LocalLoop::Schema::Result::Customer",
{ customerid => "customerid_fk" },
{ "foreign.id" => "self.customer_id" },
{
is_deferrable => 0,
join_type => "LEFT",
@ -183,18 +80,10 @@ __PACKAGE__->belongs_to(
},
);
=head2 organisationalid_fk
Type: belongs_to
Related object: L<Pear::LocalLoop::Schema::Result::Organisation>
=cut
__PACKAGE__->belongs_to(
"organisation",
"Pear::LocalLoop::Schema::Result::Organisation",
{ organisationalid => "organisationalid_fk" },
{ "foreign.id" => "self.organisation_id" },
{
is_deferrable => 0,
join_type => "LEFT",
@ -203,70 +92,58 @@ __PACKAGE__->belongs_to(
},
);
=head2 pending_organisations
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::PendingOrganisation>
=cut
__PACKAGE__->has_many(
"pending_organisations",
"Pear::LocalLoop::Schema::Result::PendingOrganisation",
{ "foreign.usersubmitted_fk" => "self.userid" },
{ "foreign.submitted_by_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 pending_transactions
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::PendingTransaction>
=cut
__PACKAGE__->has_many(
"pending_transactions",
"Pear::LocalLoop::Schema::Result::PendingTransaction",
{ "foreign.buyeruserid_fk" => "self.userid" },
{ "foreign.buyer_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 session_tokens
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::SessionToken>
=cut
__PACKAGE__->has_many(
"session_tokens",
"Pear::LocalLoop::Schema::Result::SessionToken",
{ "foreign.useridassignedto_fk" => "self.userid" },
{ "foreign.user_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 transactions
Type: has_many
Related object: L<Pear::LocalLoop::Schema::Result::Transaction>
=cut
__PACKAGE__->has_many(
"transactions",
"Pear::LocalLoop::Schema::Result::Transaction",
{ "foreign.buyeruserid_fk" => "self.userid" },
{ "foreign.buyer_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
sub generate_session {
my $self = shift;
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2017-02-24 17:32:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:qjAgtJR1zaUr00HsiR1aPw
my $token = Data::UUID->new->create_str();
$self->create_related(
'session_tokens',
{
token => $token,
},
);
return $token;
}
sub name {
my $self = shift;
if ( defined $self->customer_id ) {
return $self->customer->name;
} elsif ( defined $self->organisation_id ) {
return $self->organisation->name;
} else {
return undef;
}
}
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View file

@ -1,8 +1,10 @@
package Test::Pear::LocalLoop;
use Mojo::Base -base;
use Test::More;
use File::Temp;
use Test::Mojo;
use DateTime::Format::Strptime;
has config => sub {
my $file = File::Temp->new;
@ -29,7 +31,7 @@ has framework => sub {
$schema->deploy;
$schema->resultset('AgeRange')->populate([
[ qw/ agerangestring / ],
[ qw/ string / ],
[ '20-35' ],
[ '35-50' ],
[ '50+' ],
@ -38,4 +40,40 @@ has framework => sub {
return $t;
};
sub dump_error {
return sub {
my $self = shift;
if ( my $error = $self->tx->res->dom->at('pre[id="error"]') ) {
diag $error->text;
} else {
diag $self->tx->res->to_string;
}
};
}
sub register_customer {
my $self = shift;
my $args = shift;
my $json = {
usertype => 'customer',
%$args,
};
$self->framework->post_ok('/api/register' => json => $json)
->status_is(200)->or($self->dump_error)
->json_is('/success', Mojo::JSON->true)->or($self->dump_error);
}
sub login {
my $self = shift;
my $args = shift;
$self->framework->post_ok('/api/login' => json => $args)
->status_is(200)->or($self->dump_error)
->json_is('/success', Mojo::JSON->true)->or($self->dump_error);
return $self->framework->tx->res->json->{session_key};
}
1;

View file

@ -1,4 +1,5 @@
{
storage_path => 'images',
dsn => "dbi:SQLite:dbname=foodloop.db",
user => undef,
pass => undef,

View file

@ -0,0 +1,4 @@
body {
background: whitesmoke;
padding-top: 70px;
}

View file

@ -0,0 +1,39 @@
$(function() {
$('form#receipt-form').submit(function( event ) {
event.preventDefault();
event.stopPropagation();
// Create new form data object with the contents of this form
var formData = new FormData();
formData.append('file', $('#tran-file')[0].files[0]);
formData.append('json', JSON.stringify({
transaction_type: $('#tran-type').val(),
organisation_name: $('#org-name').val(),
street_name: $('#org-street').val(),
town: $('#org-town').val(),
postcode: $('#org-postcode').val(),
transaction_value: $('#tran-value').val()
}));
$.ajax({
url: $(this).attr("action"),
type: 'POST',
data: formData,
success: function(data) {
console.log(data);
alert(data.message);
$('form#receipt-form')[0].reset();
},
error: function(data) {
console.log(data);
alert(data.responseJSON.message);
},
cache: false,
contentType: false,
processData: false
});
// Stop propogation of event
return false;
});
});

25
script/deploy_db Normal file → Executable file
View file

@ -3,6 +3,9 @@
use strict;
use warnings;
use FindBin qw/ $Bin /;
use lib "$Bin/../lib";
use Pear::LocalLoop::Schema;
my @con = @ARGV;
@ -10,3 +13,25 @@ my @con = @ARGV;
my $schema = Pear::LocalLoop::Schema->connect(@con);
$schema->deploy;
$schema->resultset('AgeRange')->populate([
[ qw/ string / ],
[ '20-35' ],
[ '35-50' ],
[ '50+' ],
]);
if ( $ENV{MOJO_MODE} eq 'development' ) {
$schema->resultset('User')->create({
email => 'test@example.com',
password => 'abc123',
customer => {
name => 'Test User',
age_range_id => 1,
postcode => 'LA1 1AA',
},
administrator => {},
});
}

2
script/pear-local_loop Normal file → Executable file
View file

@ -4,7 +4,7 @@ use strict;
use warnings;
use FindBin qw/ $Bin /;
use lib '$Bin/../lib';
use lib "$Bin/../lib";
use Mojolicious::Commands;
Mojolicious::Commands->start_app("Pear::LocalLoop");

View file

@ -1,36 +1,20 @@
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
use Mojo::JSON;
use Test::Pear::LocalLoop;
use FindBin;
my $framework = Test::Pear::LocalLoop->new;
my $t = $framework->framework;
my $schema = $t->app->schema;
my $dump_error = sub { diag $t->tx->res->dom->at('pre[id="error"]')->text };
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;
}
$sqlDeployment = Mojo::File->new("$FindBin::Bin/../schema.sql")->slurp;
for (split ';', $sqlDeployment){
$dbh->do($_) or die $dbh->errstr;
}
my @accountTokens = ('a', 'b', 'c');
my $tokenStatement = $dbh->prepare('INSERT INTO AccountTokens (AccountTokenName) VALUES (?)');
foreach (@accountTokens){
my $rowsAdded = $tokenStatement->execute($_);
}
my @account_tokens = ('a', 'b', 'c');
$schema->resultset('AccountToken')->populate([
[ 'name' ],
map { [ $_ ] } @account_tokens,
]);
#This depends on "register.t", "login.t" and "upload.t" working.
@ -40,15 +24,15 @@ my $emailReno = 'reno@shinra.energy';
my $passwordReno = 'turks';
my $testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'Reno',
'token' => shift(@account_tokens),
'name' => 'Reno',
'email' => $emailReno,
'postcode' => 'E1 MP01',
'postcode' => 'SA4 3FA',
'password' => $passwordReno,
'age' => '20-35'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
print "test 2 - Create organisation user account (Choco Billy)\n";
@ -56,40 +40,39 @@ my $emailBilly = 'choco.billy@chocofarm.org';
my $passwordBilly = 'Choco';
$testJson = {
'usertype' => 'organisation',
'token' => shift(@accountTokens),
'username' => 'ChocoBillysGreens',
'token' => shift(@account_tokens),
'name' => 'ChocoBillysGreens',
'email' => $emailBilly,
'postcode' => 'E4 C12',
'postcode' => 'ST20 0LG',
'password' => $passwordBilly,
'fulladdress' => 'Chocobo Farm, Eastern Continent, Gaia'
'street_name' => 'Chocobo Farm, Eastern Continent',
'town' => 'Gaia',
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 3 - Create admin account\n";
my $emailAdmin = 'admin@foodloop.net';
my $passwordAdmin = 'ethics';
$testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'admin',
'token' => shift(@account_tokens),
'name' => 'admin',
'email' => $emailAdmin,
'postcode' => 'NW1 W01',
'postcode' => 'HD5 9XU',
'password' => $passwordAdmin,
'age' => '35-50'
'age_range' => 2
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 4 - Making 'admin' an Admin\n";
my $rufusUserId = $t->app->db->selectrow_array("SELECT UserId FROM Users WHERE Email = ?", undef, ($emailAdmin));
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Administrators")}[0],0,"No admins";
$t->app->db->prepare("INSERT INTO Administrators (UserId) VALUES (?)")->execute($rufusUserId);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Administrators")}[0],1,"1 admin";
my $rufus_user = $schema->resultset('User')->find({ email => $emailAdmin });
is $schema->resultset('Administrator')->count, 0, "No admins";
$rufus_user->find_or_create_related('administrator', {});
is $schema->resultset('Administrator')->count, 1, "1 admin";
######################################################
@ -101,17 +84,16 @@ $testJson = {
'password' => $passwordReno,
};
$t->post_ok('/api/login' => json => $testJson)
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
my $session_key = $t->tx->res->json('/session_key');
print "test 6 - add valid transaction (type 3: new organisation)\n";
my ($test1) = $t->app->db->selectrow_array("SELECT COUNT(*) FROM PendingOrganisations", undef, ());
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],0,"No unverified organisations.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],0,"No unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisation (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 0, "No unverified organisations";
is $schema->resultset('PendingTransaction')->count, 0, "No unverified transactions" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
my $nameToTestTurtle = 'Turtle\'s Paradise';
my $json = {
transaction_value => 20,
@ -124,30 +106,30 @@ my $json = {
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],1,"1 unverified organisation." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],1,"1 unverified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 1, "1 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 1, "1 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
my $newPendingTurtleOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtle })->pendingorganisationid;
my $newPendingTurtleOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtle })->id;
#print "Turtle Id: " . $newPendingTurtleOrgId . "\n";
print "test 7 - Non-admin (customer) tries to approve their organisation and fails.\n";
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgId,
pending_organisation_id => $newPendingTurtleOrgId,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(403)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/You are not an admin/i);
->json_like('/message', qr/Not Authorised/i);
print "test 8 - Logout Reno\n";
$t->post_ok('/api/logout', json => { session_key => $session_key } )
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
#End of non-admin Reno
@ -167,10 +149,11 @@ $t->post_ok('/api/login' => json => $testJson)
$session_key = $t->tx->res->json('/session_key');
print "test 10 - add valid transaction (type 3: new organisation)\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],1,"1 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],1,"1 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 1, "1 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 1, "1 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
my $nameToTestKalm = 'Kalm Inn';
$json = {
transaction_value => 10,
@ -185,14 +168,13 @@ $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jp
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],2,"2 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
my $newPendingKalmOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestKalm })->pendingorganisationid;
#print "Kalm Id: " . $newPendingKalmOrgId . "\n";
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 2, "2 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
my $newPendingKalmOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestKalm })->id;
print "test 11 - add valid transaction (type 2: unvalidated organisation)\n";
$json = {
@ -203,12 +185,13 @@ $json = {
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],3,"3 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 3, "3 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
print "test 12 - add valid transaction (type 3: new organisation)\n";
my $nameToTestJunon = 'Store';
@ -226,14 +209,12 @@ $t->post_ok('/api/upload' => form => $upload)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
my $newPendingJunonOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestJunon })->pendingorganisationid;
my $newPendingJunonOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestJunon })->id;
#print "Junon Id: " . $newPendingJunonOrgId . "\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],4,"4 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 4, "4 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
print "test 13 - add valid transaction (type 2: unvalidated organisation)\n";
$json = {
@ -245,13 +226,11 @@ $json = {
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_hasnt('/unvalidatedOrganisationId');
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],5,"5 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
->json_is('/success', Mojo::JSON->true);
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 5, "5 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
print "test 14 - add valid transaction (type 2: unvalidated organisation)\n";
$json = {
@ -263,22 +242,21 @@ $json = {
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_hasnt('/unvalidatedOrganisationId');
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],6,"6 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
->json_is('/success', Mojo::JSON->true);
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 6, "6 unverified transaction" ;
is $schema->resultset('Organisation')->count, 1, "1 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 0, "No verified transactions" ;
print "test 15 - Non-admin (organisation) tries to approve their organisation and fails.\n";
$json = {
unvalidatedOrganisationId => $newPendingKalmOrgId,
pending_organisation_id => $newPendingKalmOrgId,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(403)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/You are not an admin/i);
->json_like('/message', qr/Not Authorised/i);
print "test 16 - Logout Choco Billy\n";
$t->post_ok('/api/logout', json => { session_key => $session_key } )
@ -307,99 +285,107 @@ $t->post_ok('/api/admin-approve' => json => {})
->json_is('/success', Mojo::JSON->false)
->json_like('/message', qr/JSON is missing/i);
print "test 19 - unvalidatedOrganisationId missing (non-modify).\n";
print "test 19 - pending_organisation_id missing (non-modify).\n";
$json = {
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/unvalidatedOrganisationId is missing/i);
->content_like(qr/pending_organisation_id is missing/i);
print "test 20 - unvalidatedOrganisationId not number (non-modify).\n";
print "test 20 - pending_organisation_id not number (non-modify).\n";
$json = {
unvalidatedOrganisationId => 'Abc',
pending_organisation_id => 'Abc',
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/unvalidatedOrganisationId does not look like a number/i);
->json_like('/message', qr/pending_organisation_id is not a number/i);
print "test 21 - pending_organisation_id does not exist (non-modify).\n";
print "test 21 - unvalidatedOrganisationId does not exist (non-modify).\n";
my ($maxPendingId) = $t->app->db->selectrow_array("SELECT MAX(PendingOrganisationId) FROM PendingOrganisations", undef,());
my $maxPendingId = $schema->resultset('PendingOrganisation')->get_column('id')->max;
$json = {
unvalidatedOrganisationId => ($maxPendingId + 1),
pending_organisation_id => $maxPendingId + 1,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/the specified unvalidatedOrganisationId does not exist/i);
->json_like('/message', qr/pending_organisation_id does not exist in the database/i);
#TODO add text to see the specific one has moved.
print "test 22 - valid approval (non-modify).\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],6,"6 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified organisations.";
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 6, "6 unverified transaction";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
$json = {
unvalidatedOrganisationId => $newPendingKalmOrgId,
pending_organisation_id => $newPendingKalmOrgId,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisation." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],4,"4 unverified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],2,"2 verified organisations (choco billy and kalm inn)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],2,"2 verified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations WHERE Name = ?", undef, ($nameToTestKalm))}[0],0,"Kalm does not exist in pending orgs.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations WHERE Name = ?", undef, ($nameToTestKalm))}[0],1,"Kalm exists in verified orgs.";
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 4, "4 unverified transaction";
is $schema->resultset('Organisation')->count, 2, "2 verified organisations";
is $schema->resultset('Transaction')->count, 2, "2 verified transactions";
is $schema->resultset('PendingOrganisation')->find({ name => $nameToTestKalm }), undef, "Kalm does not exist in pending orgs.";
ok $schema->resultset('Organisation')->find({ name => $nameToTestKalm }), "Kalm exists in verified orgs.";
print "test 23 - valid approval (modify all).\n";
#TODO if we implement constraints on the input data this will fail
my $testName = "Change testing turtle name";
my $testFullAddress = "Change testing turtle address";
my $testPostCode = "Change testing turtle postcode";
my $test_name = "Change testing turtle name";
my $test_street_name = "Change testing turtle address";
my $test_town = "TestinTown";
my $test_postcode = "BN21 2RB";
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgId,
name => $testName,
fullAddress => $testFullAddress,
postCode => $testPostCode,
pending_organisation_id => $newPendingTurtleOrgId,
name => $test_name,
street_name => $test_street_name,
town => $test_town,
postcode => $test_postcode,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],1,"1 unverified organisation." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],3,"3 unverified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],3,"3 verified organisations (choco billy, kalm inn and turtle)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],3,"3 verified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations WHERE Name = ?", undef, ($nameToTestTurtle))}[0],0,"Turtle does not exist in pending orgs.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations WHERE Name = ?", undef, ($nameToTestTurtle))}[0],0,"Turtle does not exist in verified orgs, its been renamed.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations WHERE Name = ? AND FullAddress = ? AND PostCode = ?", undef, ($testName, $testFullAddress, $testPostCode))}[0],1,"Turtle exists and has been renamed in verified orgs.";
is $schema->resultset('PendingOrganisation')->count, 1, "1 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 3, "3 unverified transaction" ;
is $schema->resultset('Organisation')->count, 3, "3 verified organisation (choco billy)" ;
is $schema->resultset('Transaction')->count, 3, "3 verified transactions" ;
is $schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtle }), undef, "Turtle does not exist in pending orgs.";
is $schema->resultset('Organisation')->find({ name => $nameToTestTurtle }), undef, "original Turtle does not exists in verified orgs.";
my $turtle_result = $schema->resultset('Organisation')->find({ name => $test_name });
ok $turtle_result, "new Turtle exists in verified orgs.";
is $turtle_result->street_name, $test_street_name, 'street_name correct';
is $turtle_result->town, $test_town, 'town correct';
is $turtle_result->postcode, $test_postcode, 'postcode correct';
print "test 24 - valid approval (modify some).\n";
#TODO if we implement constraints on the input data this will fail
$testName = "Change testing junon name";
$test_name = "Change testing junon name";
$json = {
unvalidatedOrganisationId => $newPendingJunonOrgId,
name => $testName,
pending_organisation_id => $newPendingJunonOrgId,
name => $test_name,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],0,"0 unverified organisation." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],0,"0 unverified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],4,"4 verified organisations (choco billy, kalm inn, turtle and junon)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],6,"6 verified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations WHERE Name = ?", undef, ($nameToTestJunon))}[0],0,"Junon does not exist in pending orgs.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations WHERE Name = ?", undef, ($nameToTestJunon))}[0],0,"Junon does not exist in verified orgs, its been renamed.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations WHERE Name = ?", undef, ($testName))}[0],1,"Junon exists and has been renamed in verified orgs.";
is $schema->resultset('PendingOrganisation')->count, 0, "0 unverified organisation";
is $schema->resultset('PendingTransaction')->count, 0, "0 unverified transaction";
is $schema->resultset('Organisation')->count, 4, "4 verified organisations";
is $schema->resultset('Transaction')->count, 6, "6 verified transactions";
is $schema->resultset('PendingOrganisation')->find({ name => $nameToTestJunon }), undef, "Junon does not exist in pending orgs.";
is $schema->resultset('Organisation')->find({ name => $nameToTestJunon }), undef, "original Junon does not exists in verified orgs.";
my $junon_result = $schema->resultset('Organisation')->find({ name => $test_name });
ok $junon_result, "new Junon exists in verified orgs.";
##############################################

View file

@ -1,36 +1,20 @@
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
use Mojo::JSON;
use Test::Pear::LocalLoop;
use FindBin;
my $framework = Test::Pear::LocalLoop->new;
my $t = $framework->framework;
my $schema = $t->app->schema;
my $dump_error = sub { diag $t->tx->res->dom->at('pre[id="error"]')->text };
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;
}
$sqlDeployment = Mojo::File->new("$FindBin::Bin/../schema.sql")->slurp;
for (split ';', $sqlDeployment){
$dbh->do($_) or die $dbh->errstr;
}
my @accountTokens = ('a', 'b', 'c');
my $tokenStatement = $dbh->prepare('INSERT INTO AccountTokens (AccountTokenName) VALUES (?)');
foreach (@accountTokens){
my $rowsAdded = $tokenStatement->execute($_);
}
my @account_tokens = ('a', 'b', 'c');
$schema->resultset('AccountToken')->populate([
[ 'name' ],
map { [ $_ ] } @account_tokens,
]);
#This depends on "register.t", "login.t", "upload.t" and "admin-approve.t" working.
@ -40,12 +24,12 @@ my $emailReno = 'reno@shinra.energy';
my $passwordReno = 'turks';
my $testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'Reno',
'token' => shift(@account_tokens),
'name' => 'Reno',
'email' => $emailReno,
'postcode' => 'E1 MP01',
'postcode' => 'SA4 3FA',
'password' => $passwordReno,
'age' => '20-35'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -56,12 +40,13 @@ my $emailBilly = 'choco.billy@chocofarm.org';
my $passwordBilly = 'Choco';
$testJson = {
'usertype' => 'organisation',
'token' => shift(@accountTokens),
'username' => 'ChocoBillysGreens',
'token' => shift(@account_tokens),
'name' => 'ChocoBillysGreens',
'email' => $emailBilly,
'postcode' => 'E4 C12',
'postcode' => 'ST20 0LG',
'password' => $passwordBilly,
'fulladdress' => 'Chocobo Farm, Eastern Continent, Gaia'
'street_name' => 'Chocobo Farm, Eastern Continent',
town => 'Gaia',
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -73,23 +58,22 @@ my $emailAdmin = 'admin@foodloop.net';
my $passwordAdmin = 'ethics';
$testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'admin',
'token' => shift(@account_tokens),
'name' => 'admin',
'email' => $emailAdmin,
'postcode' => 'NW1 W01',
'postcode' => 'HD5 9XU',
'password' => $passwordAdmin,
'age' => '35-50'
'age_range' => 2
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 4 - Making 'admin' an Admin\n";
my $adminUserId = $t->app->db->selectrow_array("SELECT UserId FROM Users WHERE Email = ?", undef, ($emailAdmin));
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Administrators")}[0],0,"No admins";
$t->app->db->prepare("INSERT INTO Administrators (UserId) VALUES (?)")->execute($adminUserId);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Administrators")}[0],1,"1 admin";
my $rufus_user = $schema->resultset('User')->find({ email => $emailAdmin });
is $schema->resultset('Administrator')->count, 0, "No admins";
$rufus_user->find_or_create_related('administrator', {});
is $schema->resultset('Administrator')->count, 1, "1 admin";
######################################################
@ -106,10 +90,11 @@ $t->post_ok('/api/login' => json => $testJson)
my $session_key = $t->tx->res->json('/session_key');
print "test 6 - add valid transaction (type 3: new organisation)\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],0,"No unverified organisations.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],0,"No unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisation (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 0, "No unverified organisations";
is $schema->resultset('PendingTransaction')->count, 0, "No unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
my $nameToTestTurtle = 'Turtle\'s Paradise';
my $json = {
transaction_value => 20,
@ -124,12 +109,12 @@ my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],1,"1 unverified organisation." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],1,"1 unverified transaction." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 1, "1 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 1, "1 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
my $newPendingTurtleOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtle })->pendingorganisationid;
my $newPendingTurtleOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtle })->id;
print "Turtle Id: " . $newPendingTurtleOrgId . "\n";
@ -155,10 +140,10 @@ $t->post_ok('/api/login' => json => $testJson)
$session_key = $t->tx->res->json('/session_key');
print "test 9 - add valid transaction (type 3: new organisation)\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],1,"1 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],1,"1 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 1, "1 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 1, "1 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
my $nameToTestTurtlePartial = 'Turtle\'s Paradise2';
$json = {
@ -166,20 +151,20 @@ $json = {
transaction_type => 3,
organisation_name => $nameToTestTurtlePartial,
street_name => "",
town => "",
town => "Turtlesville",
postcode => "",
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],2,"2 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 2, "2 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
my $newPendingTurtleOrgIdPartial = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtlePartial })->pendingorganisationid;
my $newPendingTurtleOrgIdPartial = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtlePartial })->id;
print "Turtle Id 2: " . $newPendingTurtleOrgIdPartial . "\n";
#done_testing();
@ -197,11 +182,10 @@ $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jp
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],3,"3 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 3, "3 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
print "test 11 - add valid transaction (type 3: new organisation)\n";
my $nameToTestJunon = 'Store';
@ -219,14 +203,13 @@ $t->post_ok('/api/upload' => form => $upload)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
my $newPendingJunonOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestJunon })->pendingorganisationid;
my $newPendingJunonOrgId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestJunon })->id;
print "Junon Id: " . $newPendingJunonOrgId . "\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],4,"4 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 4, "4 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
print "test 12 - add valid transaction (type 2: unvalidated organisation)\n";
$json = {
@ -239,11 +222,10 @@ $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jp
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],5,"5 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 5, "5 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
print "test 13 - add valid transaction (type 2: unvalidated organisation)\n";
$json = {
@ -256,11 +238,10 @@ $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jp
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],6,"6 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisations (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions." ;
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 6, "6 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
print "test 14 - Logout Choco Billy\n";
$t->post_ok('/api/logout', json => { session_key => $session_key } )
@ -284,23 +265,23 @@ $t->post_ok('/api/login' => json => $testJson)
$session_key = $t->tx->res->json('/session_key');
print "test 16 - Admin - Approve the correctly filled out organisation.\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],3,"3 unverified organisations.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],6,"6 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],1,"1 verified organisation (choco billy)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],0,"No verified transactions.";
is $schema->resultset('PendingOrganisation')->count, 3, "3 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 6, "6 unverified transactions";
is $schema->resultset('Organisation')->count, 1, "1 verified organisation";
is $schema->resultset('Transaction')->count, 0, "No verified transactions";
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgId,
pending_organisation_id => $newPendingTurtleOrgId,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
my $turtleValidatedId = $t->app->schema->resultset('Organisation')->find({ name => $nameToTestTurtle })->organisationalid;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisations.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],5,"5 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],2,"2 verified organisations (choco billy and turtle)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],1,"1 verified transaction.";
my $turtleValidatedId = $t->app->schema->resultset('Organisation')->find({ name => $nameToTestTurtle })->id;
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 5, "5 unverified transactions";
is $schema->resultset('Organisation')->count, 2, "2 verified organisation";
is $schema->resultset('Transaction')->count, 1, "1 verified transactions";
print "test 17 - Logout Admin\n";
$t->post_ok('/api/logout', json => { session_key => $session_key } )
@ -325,14 +306,14 @@ $session_key = $t->tx->res->json('/session_key');
print "test 19 - Attempt to merge own unvalidated organisation with validated one and fails.\n";
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgIdPartial,
validatedOrganisationId => $turtleValidatedId,
pending_organisation_id => $newPendingTurtleOrgIdPartial,
target_organisation_id => $turtleValidatedId,
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(403)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/You are not an admin/i);
->json_like('/message', qr/Not Authorised/i);
print "test 20 - Logout Choco Billy\n";
$t->post_ok('/api/logout', json => { session_key => $session_key })
@ -362,98 +343,105 @@ $t->post_ok('/api/admin-merge' => json => {})
->json_like('/message', qr/JSON is missing/);
print "test 23 - unvalidatedOrganisationId missing.\n";
print "test 23 - pending_organisation_id missing.\n";
$json = {
validatedOrganisationId => $turtleValidatedId,
target_organisation_id => $turtleValidatedId,
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/unvalidatedOrganisationId is missing/i);
->json_like('/message', qr/pending_organisation_id is missing/i);
print "test 24 - unvalidatedOrganisationId not number.\n";
print "test 24 - pending_organisation_id not number.\n";
$json = {
unvalidatedOrganisationId => "ABC",
validatedOrganisationId => $turtleValidatedId,
pending_organisation_id => "ABC",
target_organisation_id => $turtleValidatedId,
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/unvalidatedOrganisationId does not look like a number/i);
->content_like(qr/pending_organisation_id is not a number/i);
print "test 25 - validatedOrganisationId missing.\n";
print "test 25 - target_organisation_id missing.\n";
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgIdPartial,
pending_organisation_id => $newPendingTurtleOrgIdPartial,
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/validatedOrganisationId is missing/i);
->content_like(qr/target_organisation_id is missing/i);
print "test 26 - validatedOrganisationId not number.\n";
print "test 26 - target_organisation_id not number.\n";
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgIdPartial,
validatedOrganisationId => "ABC",
pending_organisation_id => $newPendingTurtleOrgIdPartial,
target_organisation_id => "ABC",
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/validatedOrganisationId does not look like a number/i);
->content_like(qr/target_organisation_id is not a number/i);
print "test 27 - unvalidatedOrganisationId does not exist.\n";
my ($maxPendingId) = $t->app->db->selectrow_array("SELECT MAX(PendingOrganisationId) FROM PendingOrganisations", undef,());
print "test 27 - pending_organisation_id does not exist.\n";
my $maxPendingId = $schema->resultset('PendingOrganisation')->get_column('id')->max;
$json = {
unvalidatedOrganisationId => ($maxPendingId + 1),
validatedOrganisationId => $turtleValidatedId,
pending_organisation_id => ($maxPendingId + 1),
target_organisation_id => $turtleValidatedId,
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/unvalidatedOrganisationId does not exist in the database/i);
->content_like(qr/pending_organisation_id does not exist in the database/i);
print "test 28 - validatedOrganisationId does not exist.\n";
my ($maxId) = $t->app->db->selectrow_array("SELECT MAX(OrganisationalId) FROM Organisations", undef,());
print "test 28 - target_organisation_id does not exist.\n";
my $maxId = $schema->resultset('Organisation')->get_column('id')->max;
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgIdPartial,
validatedOrganisationId => ($maxId + 1),
pending_organisation_id => $newPendingTurtleOrgIdPartial,
target_organisation_id => ($maxId + 1),
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/validatedOrganisationId does not exist in the database/i);
->content_like(qr/target_organisation_id does not exist in the database/i);
my ($name, $fullAddress, $postCode) = $t->app->db->selectrow_array("SELECT Name, FullAddress, PostCode FROM Organisations WHERE OrganisationalId = ?", undef, ($turtleValidatedId));
my $turtle_result = $schema->resultset('Organisation')->find($turtleValidatedId);
my $old_name = $turtle_result->name;
my $old_street_name = $turtle_result->street_name;
my $old_postcode = $turtle_result->postcode;
my $old_town = $turtle_result->town;
print "test 29 - valid merge.\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],2,"2 unverified organisations.";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],5,"5 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],2,"2 verified organisations (choco billy and turtle)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],1,"1 verified transaction.";
is $schema->resultset('PendingOrganisation')->count, 2, "2 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 5, "5 unverified transactions";
is $schema->resultset('Organisation')->count, 2, "2 verified organisation";
is $schema->resultset('Transaction')->count, 1, "1 verified transactions";
is $turtle_result->transactions->count, 1, '1 transactions for turtle';
$json = {
unvalidatedOrganisationId => $newPendingTurtleOrgIdPartial,
validatedOrganisationId => $turtleValidatedId,
pending_organisation_id => $newPendingTurtleOrgIdPartial,
target_organisation_id => $turtleValidatedId,
session_key => $session_key,
};
$t->post_ok('/api/admin-merge' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations", undef, ())}[0],1,"1 unverified organisation." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions", undef, ())}[0],3,"3 unverified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations", undef, ())}[0],2,"2 verified organisations (choco billy and turtle)" ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions", undef, ())}[0],3,"3 verified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions WHERE SellerOrganisationId_FK = ?", undef, ($turtleValidatedId))}[0],3,"3 verified transactions." ;
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Organisations WHERE OrganisationalId = ? AND Name = ? AND FullAddress = ? AND PostCode = ?", undef, ($turtleValidatedId, $name, $fullAddress, $postCode))}[0],1,"Turtle exists with all orginal values.";
is $schema->resultset('PendingOrganisation')->count, 1, "1 unverified organisations";
is $schema->resultset('PendingTransaction')->count, 3, "3 unverified transactions";
is $schema->resultset('Organisation')->count, 2, "2 verified organisation";
is $schema->resultset('Transaction')->count, 3, "3 verified transactions";
is $turtle_result->transactions->count, 3, '3 transactions for turtle';
is $turtle_result->name, $old_name, 'name unchanged';
is $turtle_result->town, $old_town, 'town unchanged';
is $turtle_result->postcode, $old_postcode, 'postcode unchanged';
is $turtle_result->street_name, $old_street_name, 'street_name unchanged';
done_testing();

View file

@ -27,15 +27,13 @@ $schema->deploy;
$schema->resultset('User')->create({
email => 'admin@example.com',
hashedpassword => 'abc123',
password => 'abc123',
administrator => {},
joindate => DateTime->now,
});
$schema->resultset('User')->create({
email => 'user@example.com',
hashedpassword => 'abc123',
joindate => DateTime->now,
password => 'abc123',
});
is $schema->resultset('User')->count, 2, 'Users Created';

View file

@ -13,17 +13,17 @@ my $email = 'rufus@shinra.energy';
my $password = 'MakoGold';
$schema->resultset('AccountToken')->create({
accounttokenname => $account_token
name => $account_token
});
my $test_json = {
'usertype' => 'customer',
'token' => $account_token,
'username' => 'RufusShinra',
'name' => 'RufusShinra',
'email' => $email,
'postcode' => 'LA1 1AA',
'password' => $password,
'age' => '20-35'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $test_json)
->status_is(200)

56
t/api/user.t Normal file
View file

@ -0,0 +1,56 @@
use Mojo::Base -strict;
use Test::More;
use Mojo::JSON;
use Test::Pear::LocalLoop;
use DateTime;
my $framework = Test::Pear::LocalLoop->new;
my $t = $framework->framework;
my $schema = $t->app->schema;
my $account_token = 'a';
my $email = 'test@example.com';
my $password = 'abc123';
$schema->resultset('AccountToken')->create({
name => $account_token
});
$framework->register_customer({
'token' => $account_token,
'name' => 'Test User',
'email' => $email,
'postcode' => 'LA1 1AA',
'password' => $password,
'age_range' => 1
});
my $session_key = $framework->login({
email => $email,
password => $password,
});
my $json_no_date = { session_key => $session_key };
$t->post_ok('/api/user/day', json => $json_no_date)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
my $json_invalid_date = {
session_key => $session_key,
day => 'invalid',
};
$t->post_ok('/api/user/day', json => $json_invalid_date)
->status_is(400)->or($framework->dump_error)
->json_is('/success', Mojo::JSON->false)
->json_like('/message', qr/Invalid ISO8601 Datetime/);
my $json_valid_date = {
session_key => $session_key,
day => $t->app->datetime_formatter->format_datetime(DateTime->now),
};
$t->post_ok('/api/user/day', json => $json_valid_date)
->status_is(200)->or($framework->dump_error)
->json_is('/success', Mojo::JSON->true);
done_testing;

View file

@ -7,6 +7,7 @@ use Test::Pear::LocalLoop;
my $framework = Test::Pear::LocalLoop->new;
my $t = $framework->framework;
my $schema = $t->app->schema;
my $dump_error = sub { diag $t->tx->res->dom->at('pre[id="error"]')->text };
#Variables to be used for uniqueness when testing.
my @names = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
@ -14,13 +15,13 @@ my @emails = ('a@a.com', 'b@a.com', 'c@a.com', 'd@a.com', 'e@a.com', 'f@a.com',
my @tokens = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
$schema->resultset('AccountToken')->populate([
[ qw/ accounttokenname / ],
[ qw/ name / ],
map { [ $_ ] } @tokens,
]);
#No JSON sent
$t->post_ok('/api/register')
->status_is(400)
->status_is(400)->or($dump_error)
->json_is('/success', Mojo::JSON->false)
->json_like('/message', qr/JSON is missing/i);
@ -32,11 +33,11 @@ $t->post_ok('/api/register' => json => $testJson)
#token missing JSON
$testJson = {
'usertype' => 'customer',
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -48,11 +49,11 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => ' ',
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(401)
@ -60,64 +61,49 @@ $t->post_ok('/api/register' => json => $testJson)
->content_like(qr/token/i)
->content_like(qr/invalid/i);
#username missing JSON
#name missing JSON
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/no username sent/i);
->content_like(qr/no name sent/i);
#Blank username
#Blank name
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => '',
'name' => '',
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/blank/i)
->content_like(qr/username/i);
->content_like(qr/name/i);
#Not alpha numeric chars e.g. !
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => 'asa!',
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/username/i);
my $usernameToReuse = shift(@names);
my $nameToReuse = shift(@names);
my $emailToReuse = shift(@emails);
#Valid customer
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => $usernameToReuse,
'name' => $nameToReuse,
'email' => $emailToReuse,
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -127,11 +113,11 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '35-50'
'age_range' => 2
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -141,39 +127,24 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '20-35'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
#Username exists
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => $usernameToReuse,
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(403)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/exists/i);
#email missing JSON
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -184,11 +155,11 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => 'dfsd@.com',
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '35-50'
'age_range' => 2
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -200,11 +171,11 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => 'dfsd@com',
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '35-50'
'age_range' => 2
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -216,11 +187,11 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => $emailToReuse,
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '35-50'
'age_range' => 2
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(403)
@ -232,10 +203,10 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -248,10 +219,10 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -263,11 +234,11 @@ $t->post_ok('/api/register' => json => $testJson)
#usertype missing JSON
$testJson = {
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => '50+'
'age_range' => 3
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
@ -278,7 +249,7 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'organisation1',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
@ -291,11 +262,11 @@ $t->post_ok('/api/register' => json => $testJson)
->content_like(qr/invalid/i);
#age missing JSON
#age_range missing JSON
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
@ -303,29 +274,29 @@ $testJson = {
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/no age sent/i);
->content_like(qr/no age_range sent/i);
#Age is invalid
$testJson = {
'usertype' => 'customer',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'age' => 'invalid'
'age_range' => 'invalid'
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/age/i)
->content_like(qr/age_range/i)
->content_like(qr/invalid/i);
#full address missing JSON
$testJson = {
'usertype' => 'organisation',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
@ -333,7 +304,7 @@ $testJson = {
$t->post_ok('/api/register' => json => $testJson)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/no fulladdress sent/i);
->content_like(qr/no street_name sent/i);
#TODO Validation of full address
@ -341,11 +312,12 @@ $t->post_ok('/api/register' => json => $testJson)
$testJson = {
'usertype' => 'organisation',
'token' => shift(@tokens),
'username' => shift(@names),
'name' => shift(@names),
'email' => shift(@emails),
'postcode' => 'LA1 1AA',
'password' => 'Meh',
'fulladdress' => 'mary lane testing....'
'street_name' => 'mary lane testing....',
'town' => 'Lancaster',
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)

View file

@ -1,63 +1,28 @@
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
use Mojo::JSON;
use Text::ParseWords;
use Test::Pear::LocalLoop;
my $framework = Test::Pear::LocalLoop->new;
my $t = $framework->framework;
my $schema = $t->app->schema;
my $dump_error = sub { diag $t->tx->res->to_string };
use FindBin;
my @account_tokens = ('a', 'b');
$schema->resultset('AccountToken')->populate([
[ qw/ name / ],
map { [ $_ ] } @account_tokens,
]);
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;
}
$sqlDeployment = Mojo::File->new("$FindBin::Bin/../schema.sql")->slurp;
for (split ';', $sqlDeployment){
$dbh->do($_) or die $dbh->errstr;
}
my @accountTokens = ('a', 'b');
my $tokenStatement = $dbh->prepare('INSERT INTO AccountTokens (AccountTokenName) VALUES (?)');
foreach (@accountTokens){
my $rowsAdded = $tokenStatement->execute($_);
}
#TODO this should be done via the API but as that does not exist at the moment, just add them manually.
my $statement = $dbh->prepare("INSERT INTO Organisations (OrganisationalId, Name, FullAddress, PostCode) VALUES (?, ?, ?, ?)");
my $value = 1;
my ($name, $address, $postcode) = ("Avanti Bar & Restaurant","57 Main St, Kirkby Lonsdale, Cumbria","LA6 2AH");
$statement->execute($value, $name, $address, $postcode);
$value++;
($name, $address, $postcode) = ("Full House Noodle Bar","21 Common Garden St, Lancaster, Lancashire","LA1 1XD");
$statement->execute($value, $name, $address, $postcode);
$value++;
($name, $address, $postcode) = ("The Quay's Fishbar","1 Adcliffe Rd, Lancaster","LA1 1SS");
$statement->execute($value, $name, $address, $postcode);
$value++;
($name, $address, $postcode) = ("Dan's Fishop","56 North Rd, Lancaster","LA1 1LT");
$statement->execute($value, $name, $address, $postcode);
$value++;
($name, $address, $postcode) = ("Hodgeson's Chippy","96 Prospect St, Lancaster","LA1 3BH");
$statement->execute($value, $name, $address, $postcode);
#This depends on "register.t", "login.t" and "upload.t" working.
$schema->resultset('Organisation')->populate([
[ qw/ name street_name town postcode / ],
[ "Avanti Bar & Restaurant", "57 Main St", "Kirkby Lonsdale", "LA6 2AH" ],
[ "Full House Noodle Bar", "21 Common Garden St", "Lancaster", "LA1 1XD" ],
[ "The Quay's Fishbar", "1 Adcliffe Rd", "Lancaster", "LA1 1SS" ],
[ "Dan's Fishop", "56 North Rd", "Lancaster", "LA1 1LT" ],
[ "Hodgeson's Chippy", "96 Prospect St", "Lancaster", "LA1 3BH" ],
]);
#test with a customer.
print "test 1 - Create customer user account (Rufus)\n";
@ -65,15 +30,15 @@ my $emailRufus = 'rufus@shinra.energy';
my $passwordRufus = 'MakoGold';
my $testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'RufusShinra',
'token' => shift(@account_tokens),
'name' => 'RufusShinra',
'email' => $emailRufus,
'postcode' => 'LA1 1CF',
'postcode' => 'RG26 5NU',
'password' => $passwordRufus,
'age' => '20-35'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->status_is(200)->or($dump_error)
->json_is('/success', Mojo::JSON->true);
#test with an organisation.
@ -82,12 +47,13 @@ my $emailBilly = 'choco.billy@chocofarm.org';
my $passwordBilly = 'Choco';
$testJson = {
'usertype' => 'organisation',
'token' => shift(@accountTokens),
'username' => 'ChocoBillysGreens',
'token' => shift(@account_tokens),
'name' => 'ChocoBillysGreens',
'email' => $emailBilly,
'postcode' => 'LA1 1HT',
'password' => $passwordBilly,
'fulladdress' => 'Market St, Lancaster'
'street_name' => 'Market St',
'town' => 'Lancaster',
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -200,20 +166,11 @@ log_out();
print "test 10 - Login - Rufus (cookies, customer)\n";
login_rufus();
print "test 11 - search blank\n";
$t->post_ok('/api/search' => json => {
searchName => " ",
session_key => $session_key,
})
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/searchName is blank/i);
sub check_vars{
my ($searchTerm, $numValidated, $numUnvalidated) = @_;
$t->post_ok('/api/search' => json => {
searchName => $searchTerm,
search_name => $searchTerm,
session_key => $session_key,
})
->status_is(200)
@ -233,6 +190,9 @@ sub check_vars{
};
print "test 11 - search blank\n";
check_vars(" ", 5, 1);
print "test 12 - Testing expected values with 'booths'\n";
#Expect 0 validated and 0 unvalidated with "booths".
check_vars("booths", 0, 0);

View file

@ -7,45 +7,42 @@ use Test::Pear::LocalLoop;
my $framework = Test::Pear::LocalLoop->new;
my $t = $framework->framework;
my $schema = $t->app->schema;
my $dump_error = sub { diag $t->tx->res->dom->at('pre[id="error"]')->text };
my @accountTokens = ('a', 'b', 'c');
my @account_tokens = ('a', 'b', 'c');
$schema->resultset('AccountToken')->populate([
[ 'accounttokenname' ],
map { [ $_ ] } @accountTokens,
[ 'name' ],
map { [ $_ ] } @account_tokens,
]);
#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 $org_id_shinra = 1;
my $org_rs = $schema->resultset('Organisation');
is $org_rs->count, 0, "No organisations";
$org_rs->create({
organisationalid => $companyIdNumShinra,
name => $name,
fulladdress => $fullAddress,
postcode => $postcode,
id => $org_id_shinra,
name => 'Shinra Electric Power Company',
street_name => 'Sector 0, Midgar, Eastern Continent',
town => 'Gaia',
postcode => 'E1 M00',
});
is $org_rs->count, 1, "1 testing organisation";
#This depends on "register.t" and "login.t" working.
#Valid customer, this also tests that redirects are disabled for register.
print "test 1 - Create customer user account (Rufus)\n";
my $emailRufus = 'rufus@shinra.energy';
my $passwordRufus = 'MakoGold';
my $testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'RufusShinra',
'token' => shift(@account_tokens),
'name' => 'RufusShinra',
'email' => $emailRufus,
'postcode' => 'E1 MP01',
'postcode' => 'GU10 5SA',
'password' => $passwordRufus,
'age' => '20-35'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -56,12 +53,12 @@ my $emailHojo = 'hojo@shinra.energy';
my $passwordHojo = 'Mako';
$testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'ProfessorHojo',
'token' => shift(@account_tokens),
'name' => 'ProfessorHojo',
'email' => $emailHojo,
'postcode' => 'E1 MP01',
'postcode' => 'DE15 9LT',
'password' => $passwordHojo,
'age' => '35-50'
'age_range' => 1
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
@ -72,16 +69,18 @@ my $emailBilly = 'choco.billy@chocofarm.org';
my $passwordBilly = 'Choco';
$testJson = {
'usertype' => 'organisation',
'token' => shift(@accountTokens),
'username' => 'ChocoBillysGreens',
'token' => shift(@account_tokens),
'name' => 'ChocoBillysGreens',
'email' => $emailBilly,
'postcode' => 'E4 C12',
'postcode' => 'SO50 7NJ',
'password' => $passwordBilly,
'fulladdress' => 'Chocobo Farm, Eastern Continent, Gaia'
'street_name' => 'Chocobo Farm, Eastern Continent',
'town' => 'Gaia',
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
->json_is('/success', Mojo::JSON->true)
->json_like('/message', qr/Registered Successfully/);
######################################################
@ -109,7 +108,7 @@ $t->post_ok('/api/upload' => form => $upload )
print "test 6 - transaction_value missing\n";
my $json = {
transaction_type => 1,
organisation_id => $companyIdNumShinra,
organisation_id => $org_id_shinra,
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -122,7 +121,7 @@ print "test 7 - transaction_value non-numbers\n";
$json = {
transaction_value => 'Abc',
transaction_type => 1,
organisation_id => $companyIdNumShinra,
organisation_id => $org_id_shinra,
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -135,7 +134,7 @@ print "test 8 - transaction_value equal to zero\n";
$json = {
transaction_value => 0,
transaction_type => 1,
organisation_id => $companyIdNumShinra,
organisation_id => $org_id_shinra,
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -148,7 +147,7 @@ print "test 9 - transaction_value less than zero\n";
$json = {
transaction_value => -1,
transaction_type => 1,
organisation_id => $companyIdNumShinra,
organisation_id => $org_id_shinra,
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -173,7 +172,7 @@ $json = {
transaction_value => 10,
transaction_type => 4,
session_key => $session_key,
# organisation_id => $companyIdNumShinra
# organisation_id => $org_id_shinra
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
@ -199,7 +198,7 @@ $json = {
transaction_value => 10,
transaction_type => 1,
session_key => $session_key,
# organisation_id => $companyIdNumShinra
# organisation_id => $org_id_shinra
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
@ -211,7 +210,7 @@ print "test 14 - organisation_id for non-existent id. (type 1: already validated
$json = {
transaction_value => 10,
transaction_type => 1,
organisation_id => ($companyIdNumShinra + 100),
organisation_id => ($org_id_shinra + 100),
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -221,11 +220,11 @@ $t->post_ok('/api/upload' => form => $upload )
->content_like(qr/organisation_id does not exist in the database/i);
print "test 15 - valid addition. (type 1: already validated)\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions")}[0],0,"no transactions";
is $schema->resultset('Transaction')->count, 0, "no transactions";
$json = {
transaction_value => 10,
transaction_type => 1,
organisation_id => $companyIdNumShinra,
organisation_id => $org_id_shinra,
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -233,7 +232,7 @@ $t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_like('/message', qr/Upload Successful/);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions")}[0],1,"1 transaction";
is $schema->resultset('Transaction')->count, 1, "1 transaction";
# Add type 3 (new organisation) checking.
@ -253,8 +252,8 @@ $t->post_ok('/api/upload' => form => $upload )
->content_like(qr/organisation_name is missing/i);
print "test 17 - add valid transaction (type 3: new organisation)\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingOrganisations")}[0],0,"No pending organisations";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],0,"No pending transactions";
is $schema->resultset('PendingOrganisation')->count, 0, "No pending organisations";
is $schema->resultset('PendingTransaction')->count, 0, "No pending transactions";
$json = {
transaction_value => 10,
@ -270,8 +269,8 @@ $t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->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";
is $schema->resultset('PendingOrganisation')->count, 1, "1 pending organisations";
is $schema->resultset('PendingTransaction')->count, 1, "1 pending transactions";
# Add type 2 (unverified organisation) checking.
@ -336,8 +335,8 @@ $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";
my $unvalidatedOrganisationId = $org_result->id;
is $schema->resultset('PendingTransaction')->count, 1, "1 pending transactions";
$json = {
transaction_value => 10,
transaction_type => 2,
@ -349,7 +348,7 @@ $t->post_ok('/api/upload' => form => $upload )
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/organisation_id does not exist in the database/i);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],1,"1 pending transaction";
is $schema->resultset('PendingTransaction')->count, 1, "1 pending transactions";
print "test 24 - Logout Hojo\n";
$t->post_ok('/api/logout', json => { session_key => $session_key } )
@ -373,7 +372,7 @@ $t->post_ok('/api/login' => json => $testJson)
$session_key = $t->tx->res->json('/session_key');
print "test 26 - add valid transaction (type 2: existing organisation)\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],1,"1 pending transaction";
is $schema->resultset('PendingTransaction')->count, 1, "1 pending transactions";
$json = {
transaction_value => 10,
transaction_type => 2,
@ -385,7 +384,7 @@ $t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_like('/message', qr/Upload Successful/);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM PendingTransactions")}[0],2,"2 pending transaction";
is $schema->resultset('PendingTransaction')->count, 2, "2 pending transactions";
print "test 27 - Logout Rufus\n";
@ -410,11 +409,11 @@ $t->post_ok('/api/login' => json => $testJson)
$session_key = $t->tx->res->json('/session_key');
print "test 29 - organisation buy from another organisation\n";
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions")}[0],1,"1 transaction";
is $schema->resultset('Transaction')->count, 1, "1 transaction";
$json = {
transaction_value => 100000,
transaction_type => 1,
organisation_id => $companyIdNumShinra,
organisation_id => $org_id_shinra,
session_key => $session_key,
};
$upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
@ -422,7 +421,7 @@ $t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_like('/message', qr/Upload Successful/);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Transactions")}[0],2,"2 transactions";
is $schema->resultset('Transaction')->count, 2, "2 transaction";
done_testing();

View file

@ -1,806 +0,0 @@
use Mojo::Base -strict;
use Test::More skip_all => 'User History needs reworking';
use Test::Mojo;
use Mojo::JSON qw(encode_json);;
use Time::Fake;
use Data::Dumper;
use DateTime;
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 @accountTokens = ('a', 'b', 'c');
my $tokenStatement = $dbh->prepare('INSERT INTO AccountTokens (AccountTokenName) VALUES (?)');
foreach (@accountTokens){
my $rowsAdded = $tokenStatement->execute($_);
}
my $dateTimeNow = DateTime->now();
#Plus 2 days so you cannot have a bug where it goes past midnight when you run the test, plus one hour to remove odd error
my $dateTimeInitial = $dateTimeNow->clone()->truncate(to => day)->add(days => 2, hours => 1);
my $dateTimePlusTwoDays = $dateTimeInitial->clone()->add(days => 2);
my $dateTimePlusOneMonth = $dateTimeInitial->clone()->add(months => 1);
my $dateTimePlusOneYear = $dateTimeInitial->clone()->add(years => 1, days => 1);
my $dateTimePlusThreeDays = $dateTimeInitial->clone()->add(days => 3);
my $dateTimePlusOneMonthMinusOneDay = $dateTimePlusOneMonth->clone()->subtract(days => 1);
#Clock skew second diffs
my $dateTimeInitialDiff = $dateTimeInitial->delta_ms($dateTimeNow)->delta_minutes() * 60;
my $dateTimePlusTwoDaysSecondsDiff = $dateTimePlusTwoDays->delta_ms($dateTimeNow)->delta_minutes() * 60;
my $dateTimePlusOneMonthSecondsDiff = $dateTimePlusOneMonth->delta_ms($dateTimeNow)->delta_minutes() * 60;
my $dateTimePlusOneYearSecondsDiff = $dateTimePlusOneYear->delta_ms($dateTimeNow)->delta_minutes() * 60;
#Change to the initial time.
Time::Fake->offset("+" . $dateTimeInitialDiff . "s");
#This depends on "register.t", "login.t", "upload.t" and "admin-approve.t" working.
#Valid customer, this also tests that redirects are disabled for register.
print "test 1 - Create customer user account (Reno)\n";
my $emailReno = 'reno@shinra.energy';
my $passwordReno = 'turks';
my $testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'Reno',
'email' => $emailReno,
'postcode' => 'E1 MP01',
'password' => $passwordReno,
'age' => '20-35'
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 2 - Create organisation user account (Choco Billy)\n";
my $emailBilly = 'choco.billy@chocofarm.org';
my $passwordBilly = 'Choco';
my $testJson = {
'usertype' => 'organisation',
'token' => shift(@accountTokens),
'username' => 'ChocoBillysGreens',
'email' => $emailBilly,
'postcode' => 'E4 C12',
'password' => $passwordBilly,
'fulladdress' => 'Chocobo Farm, Eastern Continent, Gaia'
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 3 - Create admin account\n";
my $emailAdmin = 'admin@foodloop.net';
my $passwordAdmin = 'ethics';
my $testJson = {
'usertype' => 'customer',
'token' => shift(@accountTokens),
'username' => 'admin',
'email' => $emailAdmin,
'postcode' => 'NW1 W01',
'password' => $passwordAdmin,
'age' => '35-50'
};
$t->post_ok('/api/register' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 4 - Making 'admin' an Admin\n";
my $adminUserId = $t->app->db->selectrow_array("SELECT UserId FROM Users WHERE Email = ?", undef, ($emailAdmin));
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Administrators")}[0],0,"No admins";
$t->app->db->prepare("INSERT INTO Administrators (UserId) VALUES (?)")->execute($adminUserId);
is @{$t->app->db->selectrow_arrayref("SELECT COUNT(*) FROM Administrators")}[0],1,"1 admin";
sub logout {
$t->post_ok('/api/logout', json => { session_key => $session_key })
->status_is(200)
->json_is('/success', Mojo::JSON->true);
}
my $session_key;
sub login_reno {
$testJson = {
'email' => $emailReno,
'password' => $passwordReno,
};
$t->post_ok('/api/login' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
$session_key = $t->tx->res->json('/session_key');
}
sub login_chocobilly {
$testJson = {
'email' => $emailBilly,
'password' => $passwordBilly,
};
$t->post_ok('/api/login' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
$session_key = $t->tx->res->json('/session_key');
}
sub login_admin {
$testJson = {
'email' => $emailAdmin,
'password' => $passwordAdmin,
};
$t->post_ok('/api/login' => json => $testJson)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
$session_key = $t->tx->res->json('/session_key');
}
print "test 5 - Login non-admin Reno\n";
login_reno();
print "test 6 - Reno spends at Turtle\'s Paradise\n";
my $nameToTestTurtle = 'Turtle\'s Paradise';
$json = {
transaction_value => 10,
transaction_type => 3,
organisation_name => $nameToTestTurtle,
street_name => "Town centre",
town => " Wutai",
postcode => "NW11 8AD",
session_key => $session_key,
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
my $unvalidatedOrganisationId = $t->app->schema->resultset('PendingOrganisation')->find({ name => $nameToTestTurtle })->pendingorganisationid;
#Change to 2 days later
Time::Fake->offset("+" . $dateTimePlusTwoDaysSecondsDiff . "s");
print "test 7 - Reno spends at Turtle\'s Paradise, 2 days later, transaction 1/2\n";
$json = {
transaction_value => 20,
transaction_type => 2,
organisation_id => $unvalidatedOrganisationId,
session_key => $session_key,
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 8 - Reno spends at Turtle\'s Paradise, 2 days later, transaction 2/2\n";
$json = {
transaction_value => 40,
transaction_type => 2,
organisation_id => $unvalidatedOrganisationId,
session_key => $session_key,
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 9 - Logout non-admin Reno (time offset causes session to expire)\n";
logout();
#Change to 1 month later
Time::Fake->offset("+" . $dateTimePlusOneMonthSecondsDiff . "s");
print "test 10 - Login non-admin Reno\n";
login_reno();
print "test 11 - Reno spends at Turtle\'s Paradise, 1 month later\n";
$json = {
transaction_value => 80,
transaction_type => 2,
organisation_id => $unvalidatedOrganisationId,
session_key => $session_key,
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 12 - Logout non-admin Reno\n";
logout();
#Change to 1 year (and a bit) later
Time::Fake->offset("+" . $dateTimePlusOneYearSecondsDiff . "s");
print "test 13 - Login non-admin Reno\n";
login_reno();
print "test 14 - Reno spends at Turtle\'s Paradise, 1 year later\n";
$json = {
transaction_value => 160,
transaction_type => 2,
organisation_id => $unvalidatedOrganisationId,
session_key => $session_key,
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 15 - Logout non-admin Reno\n";
logout();
#Change to 2 days later
Time::Fake->offset("+" . $dateTimePlusTwoDaysSecondsDiff . "s");
print "test 16 - Login Admin\n";
login_admin();
print "test 17 - Admin approves Turtle\'s Paradise.\n";
$json = {
unvalidatedOrganisationId => $unvalidatedOrganisationId,
session_key => $session_key,
};
$t->post_ok('/api/admin-approve' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true);
my $validatedOrganisationId = $t->tx->res->json->{validatedOrganisationId};
print "test 18 - Logout Admin\n";
logout();
print "test 19 - Login non-admin Chocobilly\n";
login_chocobilly();
print "test 20 - Chocobilly spends at Turtle\'s Paradise, 2 days later\n";
#Added to test and see if the later values from different users merge together. They shouldn't
$json = {
transaction_value => 320,
transaction_type => 1,
organisation_id => $validatedOrganisationId,
session_key => $session_key,
};
my $upload = {json => Mojo::JSON::encode_json($json), file => {file => './t/test.jpg'}};
$t->post_ok('/api/upload' => form => $upload )
->status_is(200)
->json_is('/success', Mojo::JSON->true);
print "test 21 - Logout non-admin Chocobilly\n";
logout();
#Change back to 1 year (and a bit) later
Time::Fake->offset("+" . $dateTimePlusOneYearSecondsDiff . "s");
##Actual testing from here onwards.
print "test 22 - Login non-admin Reno\n";
login_reno();
print "test 23 - No JSON\n";
$t->post_ok('/api/user-history')
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->json_like('/message', qr/JSON is missing/);
print "test 24 - retrieveType is missing\n";
$json = {
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => $dateTimePlusThreeDays->month(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/retrieveType is missing/i);
print "test 25 - retrieveType is not a number\n";
$json = {
retrieveType => "A",
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => $dateTimePlusThreeDays->month(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/retrieveType does not look like a number/i);
print "test 26 - retrieveType is not 1 or 2\n";
$json = {
retrieveType => 0,
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => $dateTimePlusThreeDays->month(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/retrieveType can only be 1 or 2./i);
#Single tests
print "test 27 - single date - dayNumber is missing\n";
$json = {
retrieveType => 1,
monthNumber => $dateTimePlusThreeDays->month(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/dayNumber is missing./i);
print "test 28 - single date - dayNumber is not a number\n";
$json = {
retrieveType => 1,
dayNumber => "A",
monthNumber => $dateTimePlusThreeDays->month(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/dayNumber does not look like a number./i);
print "test 29 - single date - monthNumber is missing\n";
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusThreeDays->day(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/monthNumber is missing./i);
print "test 30 - single date - monthNumber is not a number\n";
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => "ABC",
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/monthNumber does not look like a number./i);
print "test 31 - single date - year is missing\n";
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => $dateTimePlusThreeDays->month(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/year is missing./i);
print "test 32 - single date - year is not a number\n";
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => $dateTimePlusThreeDays->month(),
year => "I1",
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/year does not look like a number./i);
print "test 33 - Invalid date\n";
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => ($dateTimePlusThreeDays->month() + 13),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/date is invalid./i);
#Range tests.
print "test 34 - range date - startDayNumber is missing\n";
$json = {
retrieveType => 2,
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/startDayNumber is missing./i);
print "test 35 - range date - startDayNumber is not a number\n";
$json = {
retrieveType => 2,
startDayNumber => "2ER",
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/startDayNumber does not look like a number./i);
print "test 36 - range date - startMonthNumber is missing\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/startMonthNumber is missing./i);
print "test 37 - range date - startMonthNumber is not a number\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => "Text",
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/startMonthNumber does not look like a number./i);
print "test 38 - range date - startYear is missing\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/startYear is missing./i);
print "test 39 - range date - startYear is not a number\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => "Years2",
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/startYear does not look like a number./i);
print "test 40 - Invalid start date\n";
$json = {
retrieveType => 2,
startDayNumber => ($dateTimeInitial->day() + 60),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/start date is invalid./i);
## Valid data testing.
print "test 41 - range date - endDayNumber is missing\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/endDayNumber is missing./i);
print "test 42 - range date - endDayNumber is not a number\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => "2EF",
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/endDayNumber does not look like a number./i);
print "test 43 - range date - endMonthNumber is missing\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/endMonthNumber is missing./i);
print "test 44 - range date - endMonthNumber is not a number\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => "A5G",
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/endMonthNumber does not look like a number./i);
print "test 43 - range date - endYear is missing\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/endYear is missing./i);
print "test 44 - range date - endYear is not a number\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => "ABC",
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/endYear does not look like a number./i);
print "test 40 - Invalid end date\n";
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => ($dateTimePlusOneYear->day() - 60),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(400)
->json_is('/success', Mojo::JSON->false)
->content_like(qr/end date is invalid./i);
print "test 41 - Test single day with no transactions\n";
my $expectedReturnedStats = {};
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusThreeDays->day(),
monthNumber => $dateTimePlusThreeDays->month(),
year => $dateTimePlusThreeDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats);
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 42 - Test single day with one transaction\n";
$expectedReturnedStats = {};
$expectedReturnedStats->{$dateTimeInitial->year}{$dateTimeInitial->month}{$dateTimeInitial->day} = 10;
$json = {
retrieveType => 1,
dayNumber => $dateTimeInitial->day(),
monthNumber => $dateTimeInitial->month(),
year => $dateTimeInitial->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats)->or(sub { use Data::Dumper; diag Dumper $t->tx->res });
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 43 - Test single day with multiple transactions and user separateness\n";
$expectedReturnedStats = {};
$expectedReturnedStats->{$dateTimePlusTwoDays->year}{$dateTimePlusTwoDays->month}{$dateTimePlusTwoDays->day} = 60;
$json = {
retrieveType => 1,
dayNumber => $dateTimePlusTwoDays->day(),
monthNumber => $dateTimePlusTwoDays->month(),
year => $dateTimePlusTwoDays->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats);
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 44 - Test range with no transactions\n";
#Empty range
$expectedReturnedStats = {};
$json = {
retrieveType => 2,
startDayNumber => $dateTimePlusThreeDays->day(),
startMonthNumber => $dateTimePlusThreeDays->month(),
startYear => $dateTimePlusThreeDays->year(),
endDayNumber => $dateTimePlusOneMonthMinusOneDay->day(),
endMonthNumber => $dateTimePlusOneMonthMinusOneDay->month(),
endYear => $dateTimePlusOneMonthMinusOneDay->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats);
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 45 - Test range with multiple very similar dated transactions (2 day window), test multiple transactions on a day and user separateness\n";
#Testing boundary condition one day before the next value.
$expectedReturnedStats = {};
$expectedReturnedStats->{$dateTimeInitial->year}{$dateTimeInitial->month}{$dateTimeInitial->day} = 10;
$expectedReturnedStats->{$dateTimePlusTwoDays->year}{$dateTimePlusTwoDays->month}{$dateTimePlusTwoDays->day} = 60;
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneMonthMinusOneDay->day(),
endMonthNumber => $dateTimePlusOneMonthMinusOneDay->month(),
endYear => $dateTimePlusOneMonthMinusOneDay->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats);
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 46 - Test range with multiple transactions spread over a few days, a month and a year, as well as user separateness\n";
$expectedReturnedStats = {};
$expectedReturnedStats->{$dateTimeInitial->year}{$dateTimeInitial->month}{$dateTimeInitial->day} = 10;
$expectedReturnedStats->{$dateTimePlusTwoDays->year}{$dateTimePlusTwoDays->month}{$dateTimePlusTwoDays->day} = 60;
$expectedReturnedStats->{$dateTimePlusOneMonth->year}{$dateTimePlusOneMonth->month}{$dateTimePlusOneMonth->day} = 80;
$expectedReturnedStats->{$dateTimePlusOneYear->year}{$dateTimePlusOneYear->month}{$dateTimePlusOneYear->day} = 160;
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats);
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 47 - Logout non-admin Reno\n";
logout();
print "test 48 - Login non-admin Chocobilly\n";
login_chocobilly();
print "test 49- Test user separateness under different user.\n";
$expectedReturnedStats = {};
$expectedReturnedStats->{$dateTimePlusTwoDays->year}{$dateTimePlusTwoDays->month}{$dateTimePlusTwoDays->day} = 320;
$json = {
retrieveType => 2,
startDayNumber => $dateTimeInitial->day(),
startMonthNumber => $dateTimeInitial->month(),
startYear => $dateTimeInitial->year(),
endDayNumber => $dateTimePlusOneYear->day(),
endMonthNumber => $dateTimePlusOneYear->month(),
endYear => $dateTimePlusOneYear->year(),
session_key => $session_key,
};
$t->post_ok('/api/user-history' => json => $json)
->status_is(200)
->json_is('/success', Mojo::JSON->true)
->json_has('/microCurencySpent')
->json_is('/microCurencySpent',$expectedReturnedStats);
my $spend = $t->tx->res->json->{microCurencySpent};
print Dumper($spend) . "\n";
print "test 50 - Logout non-admin Chocobilly\n";
logout();
done_testing();

View file

@ -23,4 +23,24 @@
</h2>
</div>
</div>
<div class="card text-center">
<div class="card-header card-inverse card-danger">
Pending Organisations
</div>
<div class="card-block">
<h2 class="card-title">
%= $pending_orgs
</h2>
</div>
</div>
<div class="card text-center">
<div class="card-header card-inverse card-danger">
Pending Transactions
</div>
<div class="card-block">
<h2 class="card-title">
%= $pending_trans
</h2>
</div>
</div>
</div>

View file

@ -0,0 +1,52 @@
% layout 'admin';
% title 'Organisations';
% content_for javascript => begin
% end
% if ( my $error = flash 'error' ) {
<div class="alert alert-danger" role="alert">
<strong>Error!</strong> <%= $error %>
</div>
% } elsif ( my $success = flash 'success' ) {
<div class="alert alert-success" role="alert">
<strong>Success!</strong> <%= $success %>
</div>
% }
<div class="row">
<div class="col">
<div class="card">
<h3 class="card-header">
Valid Organisations
</h3>
<div class="list-group list-group-flush">
% for my $valid_org ($valid_orgs_rs->all) {
<a href="<%= url_for . '/valid/' . $valid_org->id %>" class="list-group-item list-group-item-action">
<div>
%= $valid_org->name
</div>
</a>
% }
</div>
</div>
</div>
<div class="col">
<div class="card">
<h3 class="card-header">
Pending Organisations
</h3>
<div class="list-group list-group-flush">
% if ( $pending_orgs_rs->count == 0 ) {
<div class="list-group-item">
No Pending Organisations!
</div>
% } else {
% for my $pending_org ($pending_orgs_rs->all) {
<a href="<%= url_for . '/pending/' . $pending_org->id %>" class="list-group-item list-group-item-action">
<div>
%= $pending_org->name
</div>
</a>
% }}
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,42 @@
% layout 'admin';
% title 'Organisations';
% content_for javascript => begin
% end
% if ( my $error = flash 'error' ) {
<div class="alert alert-danger" role="alert">
<strong>Error!</strong> <%= $error %>
</div>
% } elsif ( my $success = flash 'success' ) {
<div class="alert alert-success" role="alert">
<strong>Success!</strong> <%= $success %>
</div>
% }
<div class="card mb-3">
<h3 class="card-header">
%= $pending_org->name
</h3>
<ul class="list-group list-group-flush">
<li class="list-group-item">Street Name: <%= $pending_org->street_name %></li>
<li class="list-group-item">Town: <%= $pending_org->town %></li>
<li class="list-group-item">Postcode: <%= $pending_org->postcode %></li>
<li class="list-group-item"><a href="<%= url_for . '/approve' %>" class="btn btn-success">Approve Organisation</a></li>
</ul>
</div>
<div class="card mb-3">
<h3 class="card-header">
Transactions
</h3>
<ul class="list-group list-group-flush">
% for my $transaction ( $pending_org->transactions->all ) {
<li class="list-group-item">
<div class="container">
<div class="row text-center">
<div class="col">From: <%= $transaction->buyer->name %></div>
<div class="col">To: <%= $transaction->seller->name %></div>
<div class="col">Value: <%= $transaction->value %></div>
</div>
</div>
</li>
% }
</ul>
</div>

View file

@ -0,0 +1,41 @@
% layout 'admin';
% title 'Organisations';
% content_for javascript => begin
% end
% if ( my $error = flash 'error' ) {
<div class="alert alert-danger" role="alert">
<strong>Error!</strong> <%= $error %>
</div>
% } elsif ( my $success = flash 'success' ) {
<div class="alert alert-success" role="alert">
<strong>Success!</strong> <%= $success %>
</div>
% }
<div class="card mb-3">
<h3 class="card-header">
%= $valid_org->name
</h3>
<ul class="list-group list-group-flush">
<li class="list-group-item">Street Name: <%= $valid_org->street_name %></li>
<li class="list-group-item">Town: <%= $valid_org->town %></li>
<li class="list-group-item">Postcode: <%= $valid_org->postcode %></li>
</ul>
</div>
<div class="card mb-3">
<h3 class="card-header">
Transactions
</h3>
<ul class="list-group list-group-flush">
% for my $transaction ( $valid_org->transactions->all ) {
<li class="list-group-item">
<div class="container">
<div class="row text-center">
<div class="col">From: <%= $transaction->buyer->name %></div>
<div class="col">To: <%= $transaction->seller->name %></div>
<div class="col">Value: <%= $transaction->value %></div>
</div>
</div>
</li>
% }
</ul>
</div>

View file

@ -14,7 +14,7 @@
<form action="<%= url_for %>" method="post">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" placeholder="Token Text" name="token-name">
<input type="text" class="form-control" placeholder="Token Text" name="token">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Add</button>
</span>
@ -23,9 +23,9 @@
</form>
<div class="list-group">
% for my $token (@$tokens) {
<a href="<%= url_for . '/' . $token->{accounttokenid} %>" class="list-group-item list-group-item-action">
<a href="<%= url_for . '/' . $token->{id} %>" class="list-group-item list-group-item-action">
<div>
%= $token->{accounttokenname}
%= $token->{name}
</div>
<div class="ml-auto">
<%= $token->{used} == 1 ? 'Used' : 'Available' %>

View file

@ -14,11 +14,11 @@
<form action="<%= url_for %>" method="post">
<div class="form-group">
<label for="token-name">Token Name</label>
<input id="token-name" type="text" class="form-control" placeholder="Token Text" name="token-name" value="<%= $token->accounttokenname %>">
<input id="token-name" type="text" class="form-control" placeholder="Token Text" name="token" value="<%= $token->name %>">
</div>
<div class="form-group">
<label for="token-used">Token Used?</label>
<select id="token-used" class="form-control" name="token-used">
<select id="token-used" class="form-control" name="used">
<option value="0"<%= $token->used == 0 ? ' selected' : '' %>>Available</option>
<option value="1"<%= $token->used == 1 ? ' selected' : '' %>>Used</option>
</select>

View file

@ -13,7 +13,7 @@
% }
<div class="list-group">
% for my $user (@$users) {
<a href="<%= url_for . '/' . $user->{userid} %>" class="list-group-item list-group-item-action">
<a href="<%= url_for . '/' . $user->{id} %>" class="list-group-item list-group-item-action">
<div>
%= $user->{email}
</div>

View file

@ -18,11 +18,11 @@
</div>
<div class="form-group">
<label for="joindate">Join Date</label>
<input id="joindate" type="datetime" class="form-control" placeholder="Date" name="joindate" value="<%= $user->joindate %>" disabled>
<input id="joindate" type="datetime" class="form-control" placeholder="Date" name="joindate" value="<%= $user->join_date %>" disabled>
</div>
<div class="form-group">
<label for="type">Account Type</label>
<input id="type" type="text" class="form-control" value="<%= defined $user->customerid_fk ? 'Customer' : 'Organisation' %>" disabled>
<input id="type" type="text" class="form-control" value="<%= defined $user->customer_id ? 'Customer' : 'Organisation' %>" disabled>
</div>
<div class="form-group">
<button class="btn btn-primary form-control" type="submit">Update</button>

View file

@ -31,6 +31,7 @@
<a class="nav-item nav-link" href="<%= url_for '/home' %>">User Section</a>
<a class="nav-item nav-link<%= title eq 'Tokens' ? ' active' : '' %>" href="<%= url_for '/admin/tokens' %>">Tokens</a>
<a class="nav-item nav-link<%= title eq 'Users' ? ' active' : '' %>" href="<%= url_for '/admin/users' %>">Users</a>
<a class="nav-item nav-link<%= title eq 'Organisations' ? ' active' : '' %>" href="<%= url_for '/admin/organisations' %>">Organisations</a>
<a class="nav-item nav-link" href="<%= url_for '/logout' %>">Logout</a>
</div>
</div>

View file

@ -7,11 +7,11 @@
<!-- Bootstrap and jQuery js -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
%= content_for 'css';
%= stylesheet '/static/user/css/main.css';
</head>
<body>
<nav class="navbar navbar-toggleable-md fixed-top navbar-inverse bg-primary">
@ -38,7 +38,9 @@
</div>
</nav>
<%= content %>
<div class="container">
<%= content %>
</div>
%= content_for 'javascript';
</body>
</html>

View file

@ -73,8 +73,8 @@ body {
<label for="register-age">Age Range</label>
<select id="register-age" class="form-control" name="agerange" required>
% for my $agerange ( @$ageranges ) {
<option value="<%= $agerange->{agerangeid} %>"<%= defined $form_data->{agerange} && $form_data->{agerange} eq $agerange->{agerangeid} ? ' selected' : '' %>>
<%= $agerange->{agerangestring} %>
<option value="<%= $agerange->{id} %>"<%= defined $form_data->{agerange} && $form_data->{agerange} eq $agerange->{id} ? ' selected' : '' %>>
<%= $agerange->{string} %>
</option>
% }
</select>

View file

@ -1,25 +1,37 @@
% layout 'user';
% title 'Home';
% content_for css => begin
<style>
body {
background: whitesmoke;
padding-top: 54px;
}
.panel {
background: white;
padding: 16px;
-webkit-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
-moz-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
}
.login-form {
margin-top: 20%;
}
</style>
% end
% content_for javascript => begin
%= javascript '/static/user/js/home.js';
% end
<div>User Pages</div>
<div class="card">
<h3 class="card-header">Submit Receipt</h3>
<div class="card-block">
<form id="receipt-form" action="<%= url_for '/portal/upload' %>">
<input id="tran-type" type="hidden" name="transaction_type" value="3" hidden>
<div class="form-group">
<label for="org-name">Organisation Name</label>
<input id="org-name" type="text" class="form-control" name="organisation_name" placeholder="Organisation Name" required>
</div>
<div class="form-group">
<label for="org-street">Street Address</label>
<input id="org-street" type="text" class="form-control" name="street_name" placeholder="eg. 7 High Street">
</div>
<div class="form-group">
<label for="org-town">Town</label>
<input id="org-town" type="text" class="form-control" name="town" placeholder="eg. Lancaster" required>
</div>
<div class="form-group">
<label for="org-postcode">Postcode</label>
<input id="org-postcode" type="text" class="form-control" name="postcode" placeholder="eg. LA1 1AA">
</div>
<div class="form-group">
<label for="tran-value">Receipt Value</label>
<input id="tran-value" type="number" step="any" class="form-control" name="transaction_value" placeholder="eg. 5.99">
</div>
<div class="form-group">
<label for="tran-file">Receipt Picture</label>
<input id="tran-file" type="file" class="form-control-file" name="file">
</div>
<button type="submit" class="btn btn-primary">Add Receipt</button>
</div>
</div>