package CF2022::Controller::Orders; use Mojo::Base 'Mojolicious::Controller'; use Mojo::UserAgent; use constant MAIN_PRODUCTS => qr/^(1|2|3)$/; # typy akreditace use constant NONFREE_PRODUCTS => qr/^(1)$/; # akreditace vyzadujici token use constant SUBSIDY_PRUDUCTS => qr/^(58)$/; # prispevkove polozky use constant FALLBACK_PRODUCT => 2; # fallback akreditace use feature 'signatures'; no warnings qw{ experimental::signatures }; sub create ($c ) { $c->openapi->valid_input or return; my $args = $c->req->json; my $claims; my $group; my @products = (); my $accredited = 0; my $accreditation = 0; my $url = sprintf ('%s/organizers/%s/events/%s/orders/', $c->config->{pretix_api}, $c->config->{pretix_organizer}, $c->config->{pretix_event}, ); my @answers = map {{ question => $_->{question_id}, answer => $_->{response}, }} @{ $args->{responses} }; # processing tokenu if ( $args->{token} ) { $c->oauth_token($args->{token}); $claims = $c->oauth_claims; return $c->error(403, 'Invalid token') if ! $claims; $group = $c->oauth_main_group; return $c->error(403, 'Invalid token') if ! $group; $args->{name} = $claims->{name}; push @answers, ( { question => $c->config->{pretix_qid_sso}, answer => $claims->{sub}, }, { question => $c->config->{pretix_qid_region}, answer => $group->{region}, }, ); $accreditation = $c->config->{'pretix_product_' . $group->{role}}; if ( $group->{role} eq 'member' ) { $args->{email} = $claims->{preferred_username} .'@'. $c->config->{mail_domain}; } else { $args->{email} = $claims->{email}; } } # korekce akreditace PRODUCT: foreach my $product ( @{ $args->{products} } ) { next PRODUCT if $product->{id} =~ SUBSIDY_PRUDUCTS && ! $product->{price}; if ( $product->{id} =~ MAIN_PRODUCTS ) { next PRODUCT if $accredited++; # neumoznit dvoji akreditace if ( $accreditation ) { $product->{id} = $accreditation; } elsif ($product->{id} =~ NONFREE_PRODUCTS) { $product->{id} = FALLBACK_PRODUCT; } } push @products, $product; } # fallback akreditace @products = ( { id => FALLBACK_PRODUCT}, @products ) if ! $accredited; my $order = { email => $args->{email}, locale => 'en', payment_provider => 'manual', testmode => $c->config->{pretix_testmode} ? 'true' : 'false', positions => [], fees => [], }; PRODUCT: foreach my $product ( @products ) { my $item = { item => $product->{id}, variation => $product->{variation}, attendee_name => $args->{name}, price => $product->{price}, company => $args->{company}, }; $item->{answers} = \@answers if $product->{id} =~ MAIN_PRODUCTS; push @{ $order->{positions} }, $item; } # kontrola duplicity my $exists = $c->schema->resultset('Order')->search({ email => $order->{email}, api => $url, })->count; $exists ||= $c->schema->resultset('Order')->search({ sso_uuid => $claims->{sub}, api => $url, })->count if $claims; return $c->error(400, 'Duplicity' ) if $exists; # odeslani do pretixu my $ua = Mojo::UserAgent->new; my $rc = $ua->post( $url, { Authorization => 'Token ' . $c->config->{pretix_token} }, json => $order )->result; return $c->error(400, $rc->body) if ! $rc->is_success; # ukladani do lokalni databazi $c->schema->resultset('Order')->create({ ip => $c->tx->remote_address, sso_uuid => $claims->{sub}, email => $order->{email}, api => $url, request => $order, order_id => $rc->json->{code}, }); $c->render( status => 201, json => $rc->json, ); } sub exists ($c ) { $c->openapi->valid_input or return; my $key = $c->param('key'); my $field = ( $key =~ /\@/ ) ? 'email' : 'sso_uuid'; my $exists = $c->schema->resultset('Order')->search({ deleted => undef, $field => $key, })->count; $c->render( status => 200, openapi => { exists => $exists }, ); } sub get ($c ) { $c->openapi->valid_input or return; $c->oauth_token($c->tx->req->content->headers->header('X-Token')); my $claims = $c->oauth_claims; return $c->error(403, 'Invalid token') if ! $claims; my $order = $c->schema->resultset('Order')->search({ deleted => undef, sso_uuid => $claims->{sub}, })->first; return $c->error(404, 'NOT FOUND') if ! $order; # datas z pretixu $c->app->log->error($order->api . $order->order_id); my $ua = Mojo::UserAgent->new; my $rc = $ua->get( $order->api . $order->order_id . '/', { Authorization => 'Token ' . $c->config->{pretix_token} }, )->result; return $c->error(400, $rc->body) if ! $rc->is_success; $c->render( status => 200, openapi => { order => $rc->json }, ); } 1;