Updated Flow of the code (markdown)
parent
26b09e863f
commit
2e4c9b52d0
1 changed files with 116 additions and 64 deletions
|
@ -3,78 +3,130 @@ It should be noted that in all of the HTTP posts that at the end or in certain p
|
||||||
|
|
||||||
# App Start
|
# App Start
|
||||||
The server is initialised and will connect to the database if the config is correct.
|
The server is initialised and will connect to the database if the config is correct.
|
||||||
`my $config = plugin Config => {file => 'myapp.conf'};`
|
```Perl
|
||||||
`my $dbh = DBI->connect($config->{dsn},$config->{user},$config->{pass}) or die "Could not connect";`
|
my $config = plugin Config => {file => 'myapp.conf'};
|
||||||
|
my $dbh = DBI->connect($config->{dsn},$config->{user},$config->{pass}) or die "Could not connect";
|
||||||
|
```
|
||||||
|
|
||||||
# Initial Token Registration
|
# Initial Token Registration
|
||||||
When the user is given the token, they then submit initially that token to the app. At first, the code receives the token in json format from an HTTP post to "/token".
|
When the user is given the token, they then submit initially that token to the app. At first, the code receives the token in json format from an HTTP post to "/token".
|
||||||
my $json = $self->req->json;
|
`my $json = $self->req->json;`
|
||||||
my $account = $self->get_account_by_token( $json->{token} );
|
`my $account = $self->get_account_by_token( $json->{token} );`
|
||||||
The code then in a sub "get_account_by_token" pulls from the database the "username" and "keyused" field from the database in the matching row of the key that was pulled. This gives us data in "username" and "keyused".
|
The code then in a sub "get_account_by_token" pulls from the database the "username" and "keyused" field from the database in the matching row of the key that was pulled. This gives us data in "username" and "keyused".
|
||||||
sub get_account_by_username {
|
```Perl
|
||||||
my ( $self, $username ) = @_;
|
sub get_account_by_username {
|
||||||
return $self->db->selectrow_hashref(
|
my ( $self, $username ) = @_;
|
||||||
'SELECT keyused, username FROM accounts WHERE username = ?',
|
return $self->db->selectrow_hashref(
|
||||||
{},
|
'SELECT keyused, username FROM accounts WHERE username = ?',
|
||||||
$username,
|
{},
|
||||||
);
|
$username,
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
The code will then check to see if the username from the data is undefined (blank so non-existent) or if the key is defined as already having been used. If either of those are true, it will return an error and stop the operation, otherwise the code continues as though nothing has occurred.
|
The code will then check to see if the username from the data is undefined (blank so non-existent) or if the key is defined as already having been used. If either of those are true, it will return an error and stop the operation, otherwise the code continues as though nothing has occurred.
|
||||||
if ( ! defined $account || $account->{keyused} eq 't' ) {
|
```Perl
|
||||||
return $self->render( json => {
|
if ( ! defined $account || $account->{keyused} eq 't' ) {
|
||||||
success => Mojo::JSON->false,
|
return $self->render( json => {
|
||||||
message => 'Token is invalid or has already been used',
|
success => Mojo::JSON->false,
|
||||||
});
|
message => 'Token is invalid or has already been used',
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
Having passed this check, the code will send back to the app response data to the HTTP post with the username that was pulled earlier.
|
Having passed this check, the code will send back to the app response data to the HTTP post with the username that was pulled earlier.
|
||||||
return $self->render( json => {
|
```Perl
|
||||||
username => $account->{username},
|
return $self->render( json => {
|
||||||
success => Mojo::JSON->true,
|
username => $account->{username},
|
||||||
});
|
success => Mojo::JSON->true,
|
||||||
};
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
# User Registration
|
# User Registration
|
||||||
The app will proceed to registering user details after the token has been submitted and the given username returned to the user client side. The client then fills in their remaining user data in a form, which is then HTTP posted back to the server in "/upload". The server code in this specified post will receive the data in json format, then will define to "account" the username, similarly to how the token key was in the token checking.
|
The app will proceed to registering user details after the token has been submitted and the given username returned to the user client side. The client then fills in their remaining user data in a form, which is then HTTP posted back to the server in "/upload". The server code in this specified post will receive the data in json format, then will define to "account" the username, similarly to how the token key was in the token checking.
|
||||||
my $json = $self->req->json;
|
```Perl
|
||||||
my $account = $self->get_account_by_username( $json->{username} );
|
my $json = $self->req->json;
|
||||||
|
my $account = $self->get_account_by_username( $json->{username} );
|
||||||
|
```
|
||||||
Next, an if and else statement is used to first check if the username is a defined one, for whatever reason in case an http submit is received where there is an undefined username to this http post, followed by a check to see if the key has been used already.
|
Next, an if and else statement is used to first check if the username is a defined one, for whatever reason in case an http submit is received where there is an undefined username to this http post, followed by a check to see if the key has been used already.
|
||||||
unless ( defined $account ) {
|
```Perl
|
||||||
return $self->render( json => {
|
unless ( defined $account ) {
|
||||||
success => Mojo::JSON->false,
|
return $self->render( json => {
|
||||||
message => 'Username not recognised, has your token expired?',
|
|
||||||
});
|
|
||||||
} elsif ( $account->{keyused} eq 't' ) {
|
|
||||||
return $self->render( json => {
|
|
||||||
success => Mojo::JSON->false,
|
success => Mojo::JSON->false,
|
||||||
message => 'Token has already been used',
|
message => 'Username not recognised, has your token expired?',
|
||||||
});
|
});
|
||||||
|
} elsif ( $account->{keyused} eq 't' ) {
|
||||||
|
return $self->render( json => {
|
||||||
|
success => Mojo::JSON->false,
|
||||||
|
message => 'Token has already been used',
|
||||||
|
});
|
||||||
|
```
|
||||||
Assuming those checks have passed, it proceeds into preparing the insert statement into the database of the remaining userdata row which matches the username, followed by executing the insert statement.
|
Assuming those checks have passed, it proceeds into preparing the insert statement into the database of the remaining userdata row which matches the username, followed by executing the insert statement.
|
||||||
my $insert = $self->db->prepare("UPDATE accounts SET 'name' = ?, email = ?, postcode = ?, age = ?, gender = ?, grouping = ?, password = ?, keyused = ? WHERE username = ?");
|
```Perl
|
||||||
$insert->execute(
|
my $insert = $self->db->prepare("UPDATE accounts SET 'name' = ?, email = ?, postcode = ?, age = ?, gender = ?, grouping = ?, password = ?, keyused = ? WHERE username = ?");
|
||||||
|
$insert->execute(
|
||||||
@{$json}{ qw/ name email postcode age gender grouping password / }, 'True', $account->{username},
|
@{$json}{ qw/ name email postcode age gender grouping password / }, 'True', $account->{username},
|
||||||
);
|
);
|
||||||
|
```
|
||||||
|
|
||||||
# User data editing
|
# User data editing
|
||||||
It may also be a case later the user may wish to edit some of their details using the User Edit page in the app. If this occurs, the user will submit a form in the client app, then will send in a json these changed details along with the username of the user for it to be matched to in json format with an HTTP post to "/edit".
|
It may also be a case later the user may wish to edit some of their details using the User Edit page in the app. If this occurs, the user will submit a form in the client app, then will send in a json these changed details along with the username of the user for it to be matched to in json format with an HTTP post to "/edit".
|
||||||
The rest of the code hereon in matches that of user registration earlier, however at the point of checking is the key has been used in the elseif, it will check if the key has been used and if it hasn't, it will say that users key has not been used yet.
|
The rest of the code hereon in matches that of user registration earlier, however at the point of checking is the key has been used in the elseif, it will check if the key has been used and if it hasn't, it will say that users key has not been used yet.
|
||||||
} elsif ( $account->{keyused} ne 't' ) {
|
```Perl
|
||||||
return $self->render( json => {
|
} elsif ( $account->{keyused} ne 't' ) {
|
||||||
success => Mojo::JSON->false,
|
return $self->render( json => {
|
||||||
message => 'Token has not been used yet!',
|
success => Mojo::JSON->false,
|
||||||
});
|
message => 'Token has not been used yet!',
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
The data is then sent to the database and updates the relevant row.
|
The data is then sent to the database and updates the relevant row.
|
||||||
my $insert = $self->db->prepare("UPDATE accounts SET 'name' = ?, postcode = ?, age = ?, gender = ?, WHERE username = ?");
|
```Perl
|
||||||
$insert->execute(
|
my $insert = $self->db->prepare("UPDATE accounts SET 'name' = ?, postcode = ?, age = ?, gender = ?, WHERE username = ?");
|
||||||
@{$json}{ qw/ name postcode age gender / }, $account->{username},
|
$insert->execute(
|
||||||
);
|
@{$json}{ qw/ name postcode age gender / }, $account->{username},
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
# Receipt uploading
|
# Receipt uploading
|
||||||
The most complex part of the app but also the most important is uploading the receipts themselves. The client app will send the image and a number of parameters with that image upon upload to the server in an HTTP post to "/upload" using the apps own image file upload code, which the app all receives in one go.
|
The most complex part of the app but also the most important is uploading the receipts themselves. The client app will send the image and a number of parameters with that image upon upload to the server in an HTTP post to "/upload" using the apps own image file upload code, which the app all receives in one go.
|
||||||
**The code for sending the key along with the data has yet to be added to the client side and thus is commented out.** The code at first checks to see if the key sent along with it matches that username as an extra measure.
|
**The code for sending the key along with the data has yet to be added to the client side and thus is commented out in the current code.** The code at first checks to see if the key sent along with it matches that username as an extra measure.
|
||||||
# Fetch parameters to write to DB
|
```Perl
|
||||||
my $key = $self->param('key');
|
# Fetch parameters to write to DB
|
||||||
# This will include an if function to see if key matches
|
my $key = $self->param('key');
|
||||||
unless ($key eq $config->{key}) {
|
# This will include an if function to see if key matches
|
||||||
return $self->render( json => { success => Mojo::JSON->false }, status => 403 );
|
unless ($key eq $config->{key}) {
|
||||||
}
|
return $self->render( json => { success => Mojo::JSON->false }, status => 403 );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Firstly, all the parameters that were sent along with the image are defined, with the username of the user that sent them, the company at which they spent at and how much they spent.
|
||||||
|
```Perl
|
||||||
|
my $username = $self->param('username');
|
||||||
|
my $company = $self->param('company');
|
||||||
|
my $currency = $self->param('currency');
|
||||||
|
```
|
||||||
|
Next, the image is as part of the client sent with headers such as what file type it is and the like. This is used to first pull out the image type, then checked to see if it is the right file type to be an image, throwing it out the operation if it is the wrong image type. It will then rewrite the name of the file to be a timestamp with the extension attached, to keep it a valid file.
|
||||||
|
```Perl
|
||||||
|
my $file = $self->req->upload('file');
|
||||||
|
# Get image type and check extension
|
||||||
|
my $headers = $file->headers->content_type;
|
||||||
|
# Is content type wrong?
|
||||||
|
if ($headers ne 'image/jpeg') {
|
||||||
|
return $self->render( json => {
|
||||||
|
success => Mojo::JSON->false,
|
||||||
|
message => 'Wrong image extension!',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
# Rewrite header data
|
||||||
|
my $ext = '.jpg';
|
||||||
|
my $uuid = Data::UUID->new->create_str;
|
||||||
|
my $filename = $uuid . $ext;
|
||||||
|
```
|
||||||
|
The file is then moved into a directory on the server, where it is stored ad infinitum.
|
||||||
|
```Perl
|
||||||
|
$file->move_to('images/' . $filename);
|
||||||
|
```
|
||||||
|
Having added the file to the server in the relevant folder, the insert statement into the database is prepared. Inserted into the "foodloop" table is a row with the username, the other parameters aforementioned and the filename, so that the relevant file is effectively indexed in the row. After statement preparation, it is then executed.
|
||||||
|
```Perl
|
||||||
|
my $insert = $self->db->prepare('INSERT INTO foodloop (username, company, currency, filename) VALUES (?,?,?,?)');
|
||||||
|
$insert->execute($username, $company, $currency, $filename);
|
||||||
|
```
|
Reference in a new issue