From 6b08544066e3a44929b9ca841aad6f3d403dd5ef Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 8 Nov 2021 16:28:03 +0000 Subject: [PATCH] Apply additional login checks and schema changes --- .htaccess | 24 ++--- blocks/ORB/Clone.pm | 3 + blocks/ORB/Delete.pm | 3 + blocks/ORB/Edit.pm | 3 + blocks/ORB/New.pm | 3 + blocks/ORB/Search.pm | 5 +- blocks/ORB/Userbar.pm | 9 +- data/swagger.json | 4 +- data/swagger.yaml | 101 ++++++++++++++++++ index.cgi | 1 - modules/ORB/BlockSelector.pm | 3 + modules/ORB/System/Recipe.pm | 50 +++++++++ templates/default/css/new.css | 1 - .../default/userbar/profile_signedin.tem | 1 + .../default/userbar/profile_signedout.tem | 1 + 15 files changed, 192 insertions(+), 20 deletions(-) diff --git a/.htaccess b/.htaccess index 3aef86b..c0f3c9b 100755 --- a/.htaccess +++ b/.htaccess @@ -30,18 +30,18 @@ AddOutputFilterByType DEFLATE application/x-javascript # For extra efficiency, make sure cache expiration times are set for content. # For example, add the following to the webapp's : # -# ExpiresActive On -# ExpiresDefault "access plus 300 seconds" +ExpiresActive On +ExpiresDefault "access plus 300 seconds" # # And the followin on its : # -# ExpiresByType text/html "access plus 30 minutes" -# ExpiresByType text/css "access plus 1 day" -# ExpiresByType text/javascript "access plus 1 day" -# ExpiresByType image/gif "access plus 1 month" -# ExpiresByType image/jpeg "access plus 1 month" -# ExpiresByType image/jpg "access plus 1 month" -# ExpiresByType image/png "access plus 1 month" -# ExpiresByType application/x-shockwave-flash "access plus 1 day" -# ExpiresByType application/x-javascript "access plus 1 day" -# ExpiresByType application/x-icon "access plus 1 day" +ExpiresByType text/html "access plus 30 minutes" +ExpiresByType text/css "access plus 10 days" +ExpiresByType text/javascript "access plus 10 days" +ExpiresByType image/gif "access plus 1 month" +ExpiresByType image/jpeg "access plus 1 month" +ExpiresByType image/jpg "access plus 1 month" +ExpiresByType image/png "access plus 1 month" +ExpiresByType application/x-shockwave-flash "access plus 10 days" +ExpiresByType application/x-javascript "access plus 10 days" +ExpiresByType application/x-icon "access plus 10 days" diff --git a/blocks/ORB/Clone.pm b/blocks/ORB/Clone.pm index 4e1c4cc..5c15ced 100644 --- a/blocks/ORB/Clone.pm +++ b/blocks/ORB/Clone.pm @@ -249,6 +249,9 @@ sub _dispatch_ui { sub page_display { my $self = shift; + my $error = $self -> check_login(); + return $error if($error); + # Is this an API call, or a normal page operation? my $apiop = $self -> is_api_operation(); if(defined($apiop)) { diff --git a/blocks/ORB/Delete.pm b/blocks/ORB/Delete.pm index 5bdec00..4a09bef 100644 --- a/blocks/ORB/Delete.pm +++ b/blocks/ORB/Delete.pm @@ -113,6 +113,9 @@ sub _dispatch_ui { sub page_display { my $self = shift; + my $error = $self -> check_login(); + return $error if($error); + # Is this an API call, or a normal page operation? my $apiop = $self -> is_api_operation(); if(defined($apiop)) { diff --git a/blocks/ORB/Edit.pm b/blocks/ORB/Edit.pm index d71e68a..df56ee8 100644 --- a/blocks/ORB/Edit.pm +++ b/blocks/ORB/Edit.pm @@ -251,6 +251,9 @@ sub _dispatch_ui { sub page_display { my $self = shift; + my $error = $self -> check_login(); + return $error if($error); + # Is this an API call, or a normal page operation? my $apiop = $self -> is_api_operation(); if(defined($apiop)) { diff --git a/blocks/ORB/New.pm b/blocks/ORB/New.pm index 75f7b56..ce46231 100644 --- a/blocks/ORB/New.pm +++ b/blocks/ORB/New.pm @@ -192,6 +192,9 @@ sub _dispatch_ui { sub page_display { my $self = shift; + my $error = $self -> check_login(); + return $error if($error); + # Is this an API call, or a normal page operation? my $apiop = $self -> is_api_operation(); if(defined($apiop)) { diff --git a/blocks/ORB/Search.pm b/blocks/ORB/Search.pm index 2aad4d8..dd15835 100644 --- a/blocks/ORB/Search.pm +++ b/blocks/ORB/Search.pm @@ -100,13 +100,12 @@ sub _build_search_results { my $term = shift; my $origonly = shift // 1; - my $recipes = $self -> {"system"} -> {"recipe"} -> find(name => $term, - method => $term, + my $recipes = $self -> {"system"} -> {"recipe"} -> find(name => '%'.$term.'%', + method => '%'.$term.'%', ingredients => [ '%'.$term.'%' ], ingredmatch => 'any', tags => [ '%'.$term.'%' ], tagmatch => 'any', - limit => 50, searchmode => 'any', original => $origonly); diff --git a/blocks/ORB/Userbar.pm b/blocks/ORB/Userbar.pm index 6ee47ed..a31894d 100644 --- a/blocks/ORB/Userbar.pm +++ b/blocks/ORB/Userbar.pm @@ -25,7 +25,7 @@ use strict; use parent qw(ORB); use experimental qw(smartmatch); use v5.14; - +use Data::Dumper; # ============================================================================== # Bar generation @@ -47,6 +47,8 @@ sub block_display { $self -> clear_error(); + my $recipe = $self -> {"system"} -> {"recipe"} -> get_random_recipe("Mains%"); + my $urls = { "%(url-signin)s" => $self -> build_url(block => "login", fullurl => 1, pathinfo => [], @@ -96,6 +98,11 @@ sub block_display { pathinfo => [ ], params => {}, forcessl => 1), + "%(url-random)s" => $self -> build_url(block => "view", + fullurl => 1, + pathinfo => [ $recipe -> {"id"} ], + params => {}, + forcessl => 1), "%(url-shop)s" => $self -> build_url(block => "shop", fullurl => 1, pathinfo => [ ], diff --git a/data/swagger.json b/data/swagger.json index 76c0415..e28fcdc 100755 --- a/data/swagger.json +++ b/data/swagger.json @@ -8,7 +8,7 @@ "schemes": [ "https" ], - "basePath": "/orb/rest/api", + "basePath": "/rest/api", "produces": [ "application/json" ], @@ -228,4 +228,4 @@ } } } -} \ No newline at end of file +} diff --git a/data/swagger.yaml b/data/swagger.yaml index 9250897..1a76f68 100755 --- a/data/swagger.yaml +++ b/data/swagger.yaml @@ -114,6 +114,101 @@ paths: description: Unexpected error schema: $ref: '#/definitions/Error' + '/menus/{name}': + get: + tags: + - menus + summary: Fetch the information for the specified menu + description: | + This will return the information for the specified menu. + parameters: + - name: name + description: The name of the menu to return the data for, or 'active' to retrieve the user's currently active menu + in: path + type: string + required: true + default: 'active' + responses: + '200': + description: The details of the menu + schema: + $ref: '#/definitions/Menu' + '403': + description: Permission error + schema: + $ref: '#/definitions/Error' + '404': + description: Not found + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + post: + tags: + - menus + summary: Create a menu with the specified name + description: | + This will create the menu, set it as the user's active menu, and return the information for the menu. + parameters: + - name: name + description: The name of the menu to create + in: path + type: string + required: true + responses: + '200': + description: The details of the menu + schema: + $ref: '#/definitions/Menu' + '403': + description: Permission error + schema: + $ref: '#/definitions/Error' + '404': + description: Not found + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + '/menus/{name}/stage/{identifier}': + put: + tags: + - menus + summary: Stage a recipe on the specified menu + description: This will stage the recipe identified by {identifier} on the specified menu. If the menu name is 'current', the user's current menu is used. + parameters: + - name: name + description: The name of the menu to return the data for, or 'active' to retrieve the user's currently active menu + in: path + type: string + required: true + default: 'active' + - name: identifier + description: The identifier for the recipe - generally the recipe ID + in: path + type: string + required: true + responses: + '200': + description: The details of the menu + schema: + $ref: '#/definitions/Menu' + '403': + description: Permission error + schema: + $ref: '#/definitions/Error' + '404': + description: Not found + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' definitions: Ingredient: type: object @@ -147,6 +242,12 @@ definitions: type: array items: $ref: '#/definitions/Tag' + Menu: + type: object + properties: + name: + type: string + description: The name of the menu Token: type: object properties: diff --git a/index.cgi b/index.cgi index a8118d1..845b100 100755 --- a/index.cgi +++ b/index.cgi @@ -6,7 +6,6 @@ use utf8; use v5.12; -use lib qw(/var/www/webperl); use FindBin; our ($scriptpath, $fallbackpath, $contact); diff --git a/modules/ORB/BlockSelector.pm b/modules/ORB/BlockSelector.pm index 389203e..265761f 100755 --- a/modules/ORB/BlockSelector.pm +++ b/modules/ORB/BlockSelector.pm @@ -26,6 +26,7 @@ package ORB::BlockSelector; use strict; use parent qw(Webperl::BlockSelector); +use URI::Escape; # ============================================================================ # Block Selection @@ -72,6 +73,8 @@ sub get_block { # If path info is present, it needs to be shoved into the cgi object if($pathinfo) { + ($pathinfo) = uri_unescape($pathinfo) =~ m<^((:?/\*?\w+[-\*@+., \w]*)+)>; + # strip off the script if it is present $pathinfo =~ s|^(/media)?/index.cgi||; diff --git a/modules/ORB/System/Recipe.pm b/modules/ORB/System/Recipe.pm index 4768722..7f54266 100644 --- a/modules/ORB/System/Recipe.pm +++ b/modules/ORB/System/Recipe.pm @@ -327,6 +327,7 @@ sub get_recipe_list { my $mode = shift; my $exlstates = shift // [ $self -> {"settings"} -> {"config"} -> {"Recipe:status:edited"} // "Edited", $self -> {"settings"} -> {"config"} -> {"Recipe:status:deleted"} // "Deleted", + $self -> {"settings"} -> {"config"} -> {"Recipe:status:rejected"} // "Rejected", ]; $self -> clear_error(); @@ -429,6 +430,53 @@ sub get_recipe { } +## @method $ get_random_recipe($types, $exlstates) +# Fetch a random recipe from the system. +# +# +sub get_random_recipe { + my $self = shift; + my $type = shift // "%"; + my $exlstates = shift // [ $self -> {"settings"} -> {"config"} -> {"Recipe:status:edited"} // "Edited", + $self -> {"settings"} -> {"config"} -> {"Recipe:status:deleted"} // "Deleted", + $self -> {"settings"} -> {"config"} -> {"Recipe:status:rejected"} // "Rejected", + ]; + + $self -> clear_error(); + + my @params = ( $type ); + my @wherefrag = ( " `t`.`name` LIKE ? "); + + # Get the status IDs for excluded states + my $stateids = $self -> _convert_states($exlstates); + if(scalar(@{$stateids})) { + push(@wherefrag, " `r`.`status_id` NOT IN (?".(",?" x (scalar(@{$stateids}) - 1)).") "); + push(@params, @{$stateids}); + } + + # Build the where part of the query, if needed. + my $where = ""; + $where = "WHERE ".join(" AND ", @wherefrag) + if(scalar(@wherefrag)); + + my $recipes = $self -> {"dbh"} -> prepare("SELECT `r`.`id` + FROM `".$self -> {"settings"} -> {"database"} -> {"recipes"}."` AS `r` + LEFT JOIN `".$self -> {"settings"} -> {"database"} -> {"types"}."` AS `t` + ON `t`.`id` = `r`.`type_id` + $where + ORDER BY RAND() + LIMIT 1"); + $recipes -> execute(@params) + or return $self -> self_error("Unable to perform random recipe lookup: ".$self -> {"dbh"} -> errstr); + + my $recipe = $recipes -> fetchrow_hashref(); + return $self -> self_error("No random recipe selected. This should not happen!") + unless($recipe && $recipe -> {"id"}); + + return $self -> get_recipe($recipe -> {"id"}); +} + + ## @method $ get_history($recipeid, $originalid) # Fetch the history for the specified recipe. # @@ -650,6 +698,8 @@ sub find { ORDER BY $order $limit"; + print STDERR $query."\n".Dumper(@params); + my $search = $self -> {"dbh"} -> prepare($query); $search -> execute(@params) or return $self -> self_error("Unable ot perform recipe search: ".$self -> {"dbh"} -> errstr); diff --git a/templates/default/css/new.css b/templates/default/css/new.css index 6645f65..ea4534c 100644 --- a/templates/default/css/new.css +++ b/templates/default/css/new.css @@ -18,7 +18,6 @@ #ingredients li button { margin: 0px; - height: auto; } #ingredients .ui-state-highlight { diff --git a/templates/default/userbar/profile_signedin.tem b/templates/default/userbar/profile_signedin.tem index 0b9f811..d4160a3 100644 --- a/templates/default/userbar/profile_signedin.tem +++ b/templates/default/userbar/profile_signedin.tem @@ -1,4 +1,5 @@