2021-12-30 12:05:56 +01:00
package APIjsonclient ;
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright (c) Rainer Gümpelein, TeilRad GmbH
#
#Client for shareejson api
#
use strict ;
use warnings ;
use POSIX ;
use CGI ; # only for debugging
use JSON ;
use LWP::UserAgent ;
use URI::Encode ;
use Config::General ;
use Mod::Basework ;
2022-01-31 14:55:05 +01:00
use Mod::DBtank ;
2021-12-30 12:05:56 +01:00
use Data::Dumper ;
sub new {
my $ class = shift ;
my $ self = { } ;
bless ( $ self , $ class ) ;
return $ self ;
}
my $ q = new CGI ;
my $ netloc = $ q - > url ( - base = > 1 ) ;
my $ ua = LWP::UserAgent - > new ;
my $ uri_encode = URI::Encode - > new ( { encode_reserved = > 1 } ) ;
$ ua - > agent ( "APIclient $netloc" ) ;
my $ bw = new Basework ;
2022-01-31 14:55:05 +01:00
my $ dbt = new DBtank ;
2021-12-30 12:05:56 +01:00
my $ json = JSON - > new - > allow_nonref ;
sub loop_sharees {
my $ self = shift ;
my $ q = shift || "" ;
2023-03-10 11:35:56 +01:00
my $ auth = shift ;
2022-01-31 14:55:05 +01:00
my $ authraw = shift ;
2022-01-18 07:04:04 +01:00
my $ return_merchant = shift || "" ;
2023-03-22 08:24:08 +01:00
my $ last_used_operator = shift || "" ;
2021-12-30 12:05:56 +01:00
my @ keywords = $ q - > param ;
#only request keys which initated by sharee primary requests to operator
2022-03-31 21:53:53 +02:00
my $ rest_hash = { } ;
2021-12-30 12:05:56 +01:00
my $ rest = "" ;
foreach ( @ keywords ) {
2023-07-27 07:05:23 +02:00
if ( $ _ =~ /request|authcookie|system|bike|station|lang/g ) {
2021-12-30 12:05:56 +01:00
my $ val = $ q - > param ( $ _ ) ;
my $ encoded_val = $ uri_encode - > encode ( $ val ) ;
$ rest . = "$_=$encoded_val&" ;
2022-03-31 21:53:53 +02:00
$ rest_hash - > { $ _ } = "$encoded_val" ;
2021-12-30 12:05:56 +01:00
}
}
$ rest =~ s/\&$// ;
my $ response_in = { } ;
my $ globalconf_file = "/var/www/copri4/shareeconf/global.cfg" ;
my $ conf = Config::General - > new ( $ globalconf_file ) ;
my % globalconf = $ conf - > getall ;
my @ uri_operator_array = ( ) ;
my @ user_group = ( ) ;
my @ user_tour = ( ) ;
my $ fetch_hash = { } ;
2023-03-16 15:13:19 +01:00
my $ o = 0 ;
2023-01-27 06:55:30 +01:00
while ( my ( $ key , $ op_name ) = each % { $ globalconf { operator } } ) {
2021-12-30 12:05:56 +01:00
my $ ret_json = "" ;
2023-03-16 15:13:19 +01:00
my % ret_json_all = ( ) ;
my % ret_json_private = ( ) ;
my % ret_json_public = ( ) ;
my % withpub = ( ) ;
2022-01-18 07:04:04 +01:00
2022-01-31 14:55:05 +01:00
#shareetool, to loop only operators who is the shareetool by usersconf enabled
my $ users_serviceapp = { u_id = > 0 } ;
2023-01-27 06:55:30 +01:00
if ( $ return_merchant - > { aowner } && $ return_merchant - > { aowner } == 187 && $ op_name - > { database } - > { dbname } && $ authraw - > { txt17 } =~ /$op_name->{database}->{dbname}/ ) {
my $ dbh_operator = $ dbt - > dbconnect_extern ( $ op_name - > { database } - > { dbname } ) ;
2022-01-31 14:55:05 +01:00
$ users_serviceapp = $ dbt - > select_users ( $ dbh_operator , $ authraw - > { c_id } , "and int09=1" ) ;
2023-01-27 06:55:30 +01:00
$ bw - > log ( "shareetool select_users $return_merchant->{aowner} on $op_name->{database}->{dbname} $authraw->{c_id} $authraw->{txt17}" , $ users_serviceapp - > { u_id } , "" ) ;
2022-01-31 14:55:05 +01:00
}
2022-02-01 20:53:23 +01:00
#every sharee client must have a merchant_id which associate a project
2023-02-10 12:04:30 +01:00
if ( $ op_name - > { operatorApp } && ( $ users_serviceapp - > { u_id } || $ return_merchant - > { merchant_id } eq $ globalconf { website } - > { 'shareeweb-sharee' } - > { merchant_id } || ( $ return_merchant - > { project_id } eq $ op_name - > { project } ) ) ) {
2023-03-16 15:13:19 +01:00
$ o + + ;
2023-03-22 08:24:08 +01:00
#stations_available with optional caching
2023-03-16 15:13:19 +01:00
if ( $ rest_hash - > { request } eq "stations_available" ) {
push ( @ uri_operator_array , $ op_name - > { operatorApp } ) ;
#if disabled, reads DB
if ( $ op_name - > { cache_station } == 1 ) {
#primary authraw
if ( $ authraw - > { txt30 } ) {
my % prim_tarif_hash = ( ) ;
if ( $ authraw - > { txt30 } =~ /\w\s\w/ ) {
% prim_tarif_hash = map { $ _ = > 1 } split ( /\s+/ , $ authraw - > { txt30 } ) ;
2023-03-30 17:45:12 +02:00
} elsif ( $ authraw - > { txt30 } && $ authraw - > { txt30 } =~ /(\w+)/ ) {
$ prim_tarif_hash { $ 1 } = 1 ;
2023-03-16 15:13:19 +01:00
}
foreach my $ optarif ( keys ( % prim_tarif_hash ) ) {
my $ op_key = "" ;
my $ tarif_key = "" ;
if ( $ optarif =~ /([A-Z]+)(\d+)/ ) {
$ op_key = $ 1 ;
$ tarif_key = $ 2 ;
}
if ( $ op_key && $ op_key eq $ op_name - > { oprefix } ) {
#print $optarif . "---" . $op_name->{oprefix} . "\n";
$ ret_json_private { $ optarif } = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/json/stations-$optarif.json" , "" ) ;
eval {
$ bw - > log ( "$o $key) Test Decode json-caching, using 1: $op_name->{operatorApp}/json/stations-$optarif.json" , "" , "" ) ;
my $ response_in = "" ;
$ response_in = decode_json ( $ ret_json_private { $ optarif } ) ;
} ;
if ( $@ ) {
$ bw - > log ( "$o $key) Failure Test reading json-caching, using fallback 1 and generate cache just-in-time: $op_name->{operatorApp}/APIjsonserver?$rest&cachme=$tarif_key" , $ ret_json , "" ) ;
#$ret_json_private{$optarif} = $self->fetch_operator_json("$op_name->{operatorApp}/APIjsonserver",$rest);
$ self - > fetch_operator_json ( "$op_name->{operatorApp}/APIjsonserver" , "$rest&cachme=$tarif_key" ) ;
$ ret_json_private { $ optarif } = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/json/stations-$optarif.json" , "" ) ;
}
}
% ret_json_all = % ret_json_private ;
}
} #primary private Tarifs
$ withpub { $ op_name - > { oprefix } } = 0 ;
foreach my $ optarif ( keys ( % ret_json_all ) ) {
my $ opx = $ 1 if ( $ optarif =~ /([A-Z]+)(\d+)/ ) ;
if ( $ op_name - > { oprefix } eq $ opx ) {
eval {
$ bw - > log ( "$o $key) Test Decode json-caching, using 2: ret_json_private hash" , "" , "" ) ;
my $ response_in = "" ;
$ response_in = decode_json ( $ ret_json_all { $ optarif } ) ;
foreach my $ station ( keys ( % { $ response_in } ) ) {
$ withpub { $ op_name - > { oprefix } } = $ response_in - > { $ station } - > { withpub } ;
}
} ;
if ( $@ ) {
$ bw - > log ( "$o $key) Failure Test reading json-caching, No fallback for ret_json_private hash" , "" , "" ) ;
}
}
}
#print "$op_name->{oprefix}: $withpub{$op_name->{oprefix}}\n";
if ( $ withpub { $ op_name - > { oprefix } } || $ op_name - > { withpub } ) {
$ ret_json_public { $ op_name - > { oprefix } } = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/json/stations-$op_name->{oprefix}.json" , "" ) ;
eval {
$ bw - > log ( "$o $key) Test Decode json-caching, using 3: $op_name->{operatorApp}/json/stations-$op_name->{oprefix}.json" , "" , "" ) ;
my $ response_in = "" ;
$ response_in = decode_json ( $ ret_json_public { $ op_name - > { oprefix } } ) ;
} ;
if ( $@ ) {
$ bw - > log ( "$o $key) Failure Test reading json-caching, using fallback 3 and generate cache just-in-time: $op_name->{operatorApp}/APIjsonserver?$rest&cachme=public" , $ ret_json , "" ) ;
#$ret_json_public{$op_name->{oprefix}} = $self->fetch_operator_json("$op_name->{operatorApp}/APIjsonserver",$rest);
$ self - > fetch_operator_json ( "$op_name->{operatorApp}/APIjsonserver" , "$rest&cachme=public" ) ;
$ ret_json_public { $ op_name - > { oprefix } } = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/json/stations-$op_name->{oprefix}.json" , "" ) ;
}
% ret_json_all = ( % ret_json_all , % ret_json_public ) ;
}
foreach my $ optarif ( keys ( % ret_json_all ) ) {
if ( $ ret_json_all { $ optarif } ) {
eval {
$ bw - > log ( "$o $key) Test Decode json-caching, using 3: ret_json_all hash" , "" , "" ) ;
my $ response_in = "" ;
$ response_in = decode_json ( $ ret_json_all { $ optarif } ) ;
foreach my $ result ( keys ( % { $ response_in } ) ) {
$ fetch_hash - > { $ result } = $ response_in - > { $ result } ;
}
} ;
if ( $@ ) {
$ bw - > log ( "$o $key) Failure Test reading json-caching, No fallback for ret_json_all hash" , "" , "" ) ;
}
}
}
2023-03-22 08:24:08 +01:00
} #end cache_station
2023-03-16 15:13:19 +01:00
else {
$ ret_json = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/APIjsonserver" , $ rest ) ;
$ bw - > log ( "$o $key) Caching disabled, No reading json-caching, taking: $op_name->{operatorApp}/APIjsonserver?$rest" , $ ret_json , "" ) ;
2023-03-10 11:35:56 +01:00
}
2023-03-16 15:13:19 +01:00
} #end stations_available
2023-03-22 08:24:08 +01:00
#user_bike_occupied by $last_used_operator
elsif ( $ last_used_operator && $ rest_hash - > { request } eq "user_bikes_occupied" ) {
if ( $ last_used_operator eq $ op_name - > { database } - > { dbname } ) {
#$bw->log("fetch_operator_json >> user_bikes_occupied by last_used_operator:$last_used_operator ","","");
$ ret_json = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/APIjsonserver" , "$rest&withoutkey=1" ) ;
}
}
#all other operator requests
2023-03-16 15:13:19 +01:00
else {
$ ret_json = $ self - > fetch_operator_json ( "$op_name->{operatorApp}/APIjsonserver" , $ rest ) ;
}
2022-03-31 21:53:53 +02:00
2021-12-30 12:05:56 +01:00
if ( $ ret_json ) {
2023-01-27 06:55:30 +01:00
push ( @ uri_operator_array , $ op_name - > { operatorApp } ) ;
2021-12-30 12:05:56 +01:00
eval {
2022-03-31 21:53:53 +02:00
my $ response_in = "" ;
$ response_in = decode_json ( $ ret_json ) ;
#print Dumper($response_in);
2021-12-30 12:05:56 +01:00
#collect OP user_group
if ( $ response_in - > { shareejson } - > { user_group } ) {
push ( @ user_group , @ { $ response_in - > { shareejson } - > { user_group } } ) ;
}
#collect OP user_tour
if ( $ response_in - > { shareejson } - > { user_tour } ) {
push ( @ user_tour , @ { $ response_in - > { shareejson } - > { user_tour } } ) ;
}
if ( $ q - > param ( 'request' ) && $ q - > param ( 'request' ) =~ /stations_all|stations_available/ ) {
foreach my $ result ( keys ( % { $ response_in - > { shareejson } - > { stations } } ) ) {
$ fetch_hash - > { $ result } = $ response_in - > { shareejson } - > { stations } - > { $ result } ;
2023-01-30 20:59:19 +01:00
#workaround, delete contributor test stations on global sharee project Freiburg
if ( $ return_merchant - > { project_id } eq "Freiburg" && $ return_merchant - > { project_id } ne $ op_name - > { project } && $ fetch_hash - > { $ result } - > { description } =~ /Contributor/i ) {
#$bw->log("delete contributor-station $result: $fetch_hash->{$result}->{description}","","");
delete $ fetch_hash - > { $ result } ;
}
2021-12-30 12:05:56 +01:00
}
}
if ( $ q - > param ( 'request' ) && $ q - > param ( 'request' ) =~ /bikes_all|bikes_available/ ) {
foreach my $ result ( keys ( % { $ response_in - > { shareejson } - > { bikes } } ) ) {
$ fetch_hash - > { $ result } = $ response_in - > { shareejson } - > { bikes } - > { $ result } ;
}
}
if ( $ q - > param ( 'request' ) && $ q - > param ( 'request' ) =~ /user_bikes_occupied/ ) {
foreach my $ result ( keys ( % { $ response_in - > { shareejson } - > { bikes_occupied } } ) ) {
$ fetch_hash - > { $ result } = $ response_in - > { shareejson } - > { bikes_occupied } - > { $ result } ;
}
}
} ;
if ( $@ ) {
2023-03-16 15:13:19 +01:00
$ bw - > log ( "$o $key) Failure, eval json from jsonclient" , $ ret_json , "" ) ;
2021-12-30 12:05:56 +01:00
warn $@ ;
}
} else {
2023-03-16 15:13:19 +01:00
$ bw - > log ( "$o $key) NO json from Operator:" , $ op_name - > { operatorApp } , "" ) ;
2021-12-30 12:05:56 +01:00
}
2022-10-31 08:11:53 +01:00
#$bw->log("--> LOOP-end jsonclient loop_sharees user_group:\n",\@user_group,"");
2021-12-30 12:05:56 +01:00
}
2022-01-18 07:04:04 +01:00
2021-12-30 12:05:56 +01:00
}
#print "ALL:" . Dumper($fetch_hash);
#
return ( $ fetch_hash , \ @ uri_operator_array , \ @ user_group , \ @ user_tour ) ;
}
sub fetch_operator_json {
my $ self = shift ;
my $ operator_server = shift || "" ;
my $ rest = shift || "" ;
2022-03-31 21:53:53 +02:00
my $ operator_request = "$operator_server?$rest" ;
2021-12-30 12:05:56 +01:00
2023-03-22 08:24:08 +01:00
#$bw->log("fetch_operator_json >> $operator_request","$operator_request","");
2021-12-30 12:05:56 +01:00
my $ req = HTTP::Request - > new ( GET = > "$operator_request" ) ;
$ req - > content_type ( 'application/x-www-form-urlencoded' ) ;
$ req - > content ( $ rest ) ;
my $ res = $ ua - > request ( $ req ) ;
if ( $ res - > is_success ) {
#print $res->content;
2022-08-01 21:42:55 +02:00
#return $res->content;
my $ encoded = Encode:: encode ( 'utf-8' , Encode:: decode ( 'iso-8859-1' , $ res - > content ) ) ;
return $ encoded ;
2021-12-30 12:05:56 +01:00
} else {
return "" ;
}
}
1 ;