diff --git a/cgi/user2.pl b/cgi/user2.pl new file mode 100644 index 0000000000000..bc6f0d13993ac --- /dev/null +++ b/cgi/user2.pl @@ -0,0 +1,385 @@ +#!/usr/bin/perl -w + +# This file is part of Product Opener. +# +# Product Opener +# Copyright (C) 2011-2020 Association Open Food Facts +# Contact: contact@openfoodfacts.org +# Address: 21 rue des Iles, 94100 Saint-Maur des Fossés, France +# +# Product Opener is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +use Modern::Perl '2017'; +use utf8; + +use ProductOpener::Config qw/:all/; +use ProductOpener::Store qw/:all/; +use ProductOpener::Index qw/:all/; +use ProductOpener::Display qw/:all/; +use ProductOpener::Users qw/:all/; +use ProductOpener::Lang qw/:all/; +use ProductOpener::Orgs qw/:all/; + +use CGI qw/:cgi :form escapeHTML charset/; +use URI::Escape::XS; +use Storable qw/dclone/; +use Log::Any qw($log); + +my @user_groups = qw(producer database app bot moderator pro_moderator); + +my $type = param('type') || 'add'; +my $action = param('action') || 'display'; + +# Passing values to the template +my $template_data_ref = {}; + +# If the "Create user" form was submitted from the product edit page +# save the password parameter and unset it so that the ProductOpener::Display::init() +# function does not try to authenticate the user (which does not exist yet) with that password + +my $new_user_password; +if (($type eq "add") and (defined param('prdct_mult'))) { + + $new_user_password = param('password'); + param("password", ""); +} + +ProductOpener::Display::init(); + + +# $userid will contain the user to be edited, possibly different than $User_id +# if an administrator edits another user + +my $userid = $User_id; + +if (defined param('userid')) { + + $userid = param('userid'); + + # The userid looks like an e-mail + if ($admin and ($userid =~ /\@/)) { + my $emails_ref = retrieve("$data_root/users_emails.sto"); + if (defined $emails_ref->{$userid}) { + $userid = $emails_ref->{$userid}[0]; + } + } + + $userid = get_fileid($userid, 1); +} + +$log->debug("user form - start", { type => $type, action => $action, userid => $userid, User_id => $User_id }) if $log->is_debug(); + +my $html = ''; +my $js = ''; + +my $user_ref = {}; + +if ($type =~ /^edit/) { + $user_ref = retrieve("$data_root/users/$userid.sto"); + if (not defined $user_ref) { + display_error($Lang{error_invalid_user}{$lang}, 404); + } +} +else { + $type = 'add'; +} + +if (($type =~ /^edit/) and ($User_id ne $userid) and not $admin) { + display_error($Lang{error_no_permission}{$lang}, 403); +} + +my $debug = 0; +my @errors = (); + +if ($action eq 'process') { + + if ($type eq 'edit') { + if (param('delete') eq 'on') { + if ($admin) { + $type = 'delete'; + } + else { + display_error($Lang{error_no_permission}{$lang}, 403); + } + } + } + + if ($type eq 'edit_owner') { + ProductOpener::Users::check_edit_owner($user_ref, \@errors); + } + elsif ($type ne 'delete') { + ProductOpener::Users::check_user_form($type, $user_ref, \@errors); + } + + if ($#errors >= 0) { + if ($type eq 'edit_owner') { + $action = 'none'; + } + else { + $action = 'display'; + } + } +} + +$template_data_ref->{action} = $action; +$template_data_ref->{errors} = \@errors; + +$log->debug("user form - before display / process", { type => $type, action => $action, userid => $userid }) if $log->is_debug(); + +if ($action eq 'display') { + + # We can pre-fill the form to create an account using the username and password + # passed in a form to open a session. + # e.g. when a non-logged user clicks on the "Edit product" button + + if (($type eq "add") and (defined param("user_id"))) { + my $user_info = remove_tags_and_quote(param('user_id')); + $user_info =~ /^(.+?)@/; + if ( defined ($1) ){ + $user_ref->{email} = $user_info; + $user_ref->{userid} = $1; + $user_ref->{name} = $1; + $user_ref->{password} = $new_user_password; + } + else{ + $user_ref->{userid} = $user_info; + $user_ref->{name} = $user_info; + $user_ref->{password} = $new_user_password; + } + } + + $template_data_ref->{user_ref} = $user_ref; + + # Create the list of sections and fields + + $template_data_ref->{sections} = []; + + if ($user_ref) { + push @{$template_data_ref->{sections}}, { + id => "user", + fields => [ + { + field => "name" + }, + { + field => "email", + type => "email", + }, + { + field => "userid", + label => "username" + }, + { + field => "password", + type => "password", + label => "password" + }, + { + field => "confirm_password", + type => "password", + label => "password_confirm" + }, + ] + }; + + # Professional account + push @{$template_data_ref->{sections}}, { + id => "professional", + name => lang("pro_account"), + description => "if_you_work_for_a_producer", + note => "producers_platform_description_long", + fields => [ + { + field => "pro", + type => "checkbox", + label => lang("this_is_a_pro_account"), + warning => sprintf(lang("this_is_a_pro_account_for_org"),"" . $user_ref->{org} . ""), + value => "off", + }, + { + field => "pro_checkbox", + type => "hidden", + value => 1, + }, + { + field => "requested_org", + label => lang("producer_or_brand") . ":", + } + ] + }; + + # Teams section + my $team_section_ref = { + id => "teams", + name => lang("teams") . " (" . lang("optional") . ")", + description => "teams_description", + note => "teams_names_warning", + fields => [] + }; + for (my $i = 1; $i <= 3; $i++) { + push @{$team_section_ref->{fields}}, { + field => "team_". $i, + label => sprintf(lang("team_s"), $i), + }; + }; + + push @{$template_data_ref->{sections}}, {%$team_section_ref}; + + # Admin section + my $administrator_section_ref = { + id => "administrator", + name => "Administrator fields", + fields => [] + }; + push @{$administrator_section_ref->{fields}}, { + field => "org", + label => lang("organization"), + }; + foreach my $group (@user_groups) { + push @{$administrator_section_ref->{fields}}, { + field => "user_group_". $group, + label => lang("user_group_". $group) . " " . lang("user_group_" . ${group} . "_description"), + type => "checkbox", + value => $user_ref->{$group}, + }; + }; + + push @{$template_data_ref->{sections}}, {%$administrator_section_ref}; + } + + if ( ( defined $user_ref->{org} ) and ( $user_ref->{org} ne "" ) ) { + + $template_data_ref->{accepted_organization} = $user_ref->{org}; + $template_data_ref->{pro_account_org} = sprintf(lang("this_is_a_pro_account_for_org"),"" . $user_ref->{org} . ""); + } + elsif ((defined $options{product_type}) and ($options{product_type} eq "food")) { + my $requested_org_ref = retrieve_org($user_ref->{requested_org}); + $template_data_ref->{requested_org_ref} = $requested_org_ref; + $template_data_ref-> {org_name} = sprintf(lang("add_user_existing_org"), org_name($requested_org_ref)); + $template_data_ref->{teams_flag} = not ((defined $server_options{private_products}) and ($server_options{private_products})); + } + + # Add labels, types, descriptions, notes and existing values for all fields + foreach my $section_ref (@{$template_data_ref->{sections}}) { + + # Descriptions and notes for sections + if (defined $section_ref->{id}) { + if ($section_ref->{description}) { + $section_ref->{description} = lang($section_ref->{description}); + } + if ($section_ref->{note}) { + $section_ref->{note} = lang($section_ref->{note}); + } + } + + foreach my $field_ref (@{$section_ref->{fields}}) { + + my $field = $field_ref->{field}; + + # Default to text field + if (not defined $field_ref->{type}) { + $field_ref->{type} = "text"; + }; + + # id to use for lang() strings + my $field_lang_id = $field; + + if (not defined $field_ref->{value}) { + $field_ref->{value} = $user_ref->{$field}; + }; + + # Label + if (not defined $field_ref->{label}) { + $field_ref->{label} = lang($field_lang_id); + }; + + if (((defined $user_ref->{pro}) and ($user_ref->{pro})) + or ((defined $server_options{producers_platform}) and ($type eq "add"))) { + if (($section_ref->{id} eq "professional") and $field_ref->{type} eq "checkbox") { + $field_ref->{value} = "on"; + } + }; + }; + }; + +} + +elsif ($action eq 'process') { + + if (($type eq 'add') or ($type =~ /^edit/)) { + ProductOpener::Users::process_user_form($type, $user_ref); + } + elsif ($type eq 'delete') { + ProductOpener::Users::delete_user($user_ref); + } + + if ($type eq 'add') { + + $template_data_ref->{user_requested_org} = $user_ref->{requested_org}; + + my $requested_org_ref = retrieve_org($user_ref->{requested_org}); + $template_data_ref->{add_user_existing_org} = sprintf(lang("add_user_existing_org"), org_name($requested_org_ref)); + + $template_data_ref->{user_org} = $user_ref->{org}; + + $template_data_ref->{server_options_producers_platform} = $server_options{producers_platform}; + + my $pro_url = "https://" . $subdomain . ".pro." . $server_domain . "/"; + $template_data_ref->{add_user_pro_url} = sprintf(lang("add_user_you_can_edit_pro_promo"), $pro_url); + + $template_data_ref->{add_user_you_can_edit} = sprintf(lang("add_user_you_can_edit"), lang("get_the_app_link")); + $template_data_ref->{add_user_join_the_project} = sprintf(lang("add_user_join_the_project"), lang("site_name")); + } + +} + +$template_data_ref->{debug} = $debug; +$template_data_ref->{userid} = $userid; +$template_data_ref->{type} = $type; + +my $full_width = 1; +if ($action ne 'display') { + $full_width = 0; +} + +if (($type eq "edit_owner") and ($action eq "process")) { + $log->info("redirecting to / after changing owner", { }) if $log->is_info(); + + my $r = shift; + $r->headers_out->set(Location =>"/"); + $r->status(302); + return 302; +} +else { + + my $title = lang($type . '_user_' . $action); + + $log->debug("user form - template data", { template_data_ref => $template_data_ref }) if $log->is_debug(); + + process_template('user_form2.tt.html', $template_data_ref, \$html) or $html = "

" . $tt->error() . "

"; + process_template('user_form2.tt.js', $template_data_ref, \$js); + + $initjs .= $js; + $scripts .= < + +HTML +; + + display_new( { + title=>$title, + content_ref=>\$html, + full_width=>$full_width, + }); +} \ No newline at end of file diff --git a/templates/user_form2.tt.html b/templates/user_form2.tt.html new file mode 100644 index 0000000000000..75feaf4496b1e --- /dev/null +++ b/templates/user_form2.tt.html @@ -0,0 +1,212 @@ + + + + +[% IF action == 'display' || action == 'none' %] +[% INCLUDE 'error_list.tt.html' %] +[% END %] + +[% IF action == 'display' %] + + + +
+ [% FOREACH section IN sections %] + + [% IF section.name %] +
+ [% section.name %] + [% END %] + + [% IF section.description %] +

[% section.description %]

+ [% END %] + + [% IF section.note %] +

[% section.note %]

+ [% END %] + + [% FOREACH field IN section.fields %] + [% IF field.field == 'userid' %] + [% IF type == 'edit' %] + +

[% field.value %]

+ [% ELSE %] + + + [% END %] + [% ELSIF field.type == 'text' %] +
+ + +
+ [% ELSIF field.type == 'password' %] + + + [% ELSIF field.type == 'email' %] + + + [% ELSIF field.type == 'checkbox' %] + [% IF accepted_organization && section.id == "professional" %] +

[% field.warning %]

+ [% ELSE %] + + [% END %] + [% ELSIF field.type == 'hidden' %] + + [% END %] + + [% END %] + +
+ [% IF requested_org_ref.defined && section.id == "professional" %] +
+

[% org_name %]

+

[% lang("add_user_existing_org_pending") %]

+

[% lang("please_email_producers") %]

+
+ [% ELSIF section.id == "professional" && !requested_org_ref.defined %] +

[% lang("enter_name_of_org") %]

+ [% END %] +
+ + [% IF section.name %] +
+ [% END %] + + [% END %] + + + [% IF type == 'add' %] + +

[% lang("unsubscribe_info") %]

+ [% END %] + + [% IF admin %] + + [% END %] + + + [% IF userid %] + + + [% ELSE %] + + [% END %] +
+ + + +[% ELSIF action == 'process' %] +

[% lang('${type}_user_result') %]

+ + [% IF type == 'add' %] + + + + [% IF user_requested_org.defined %] + + + +
+

[% add_user_existing_org %]

+

[% lang("add_user_existing_org_pending") %]

+

[% lang("please_email_producers") %]

+
+ + [% ELSIF user_org.defined %] + + + + [% IF server_options_producers_platform.defined %] + + + + + +

[% lang("add_user_you_can_edit_pro") %]

+

[% lang("import_product_data") %]

+ + [% ELSE %] + + + +

[% add_user_pro_url %]

+ + [% END %] + + [% ELSE %] + + + + +

[% add_user_you_can_edit %]

+

[% add_user_join_the_project %]

+

[% lang("add_user_join_us_on_slack") %]

+

[% lang("join_us_on_slack") %]

+ + [% END %] + + [% END %] + + [% IF type == 'add' || type == 'edit' %] + + + + [% IF !(server_options_producers_platform) %] +

[% lang("you_can_also_help_us") %]

+

[% lang("bottom_content") %]

+ [% END %] + + [% END %] + +[% END %] + +[% IF debug %] +

type: [% type %] action: [% action %] userid: [% userid %]

+[% END %] diff --git a/templates/user_form2.tt.js b/templates/user_form2.tt.js new file mode 100644 index 0000000000000..66fe2f43bf7c4 --- /dev/null +++ b/templates/user_form2.tt.js @@ -0,0 +1,15 @@ +\$('#pro').change(function() { + if (\$(this).prop('checked')) { + \$('.pro_org_display').show(); + \$('.tr_teams').hide(); + } else { + \$('.pro_org_display').hide(); + \$('.tr_teams').show(); + } + \$(document).foundation('equalizer', 'reflow'); +}); + +if (\$('#pro').prop('checked')) { + \$('.pro_org_display').show(); + \$('.tr_teams').hide(); +} \ No newline at end of file