1 package OpenILS::WWW::EGCatLoader;
2 use strict; use warnings;
3 use Apache2::Const -compile => qw(OK FORBIDDEN HTTP_INTERNAL_SERVER_ERROR);
4 use OpenSRF::Utils::Logger qw/$logger/;
5 use OpenILS::Utils::Fieldmapper;
6 use OpenILS::Application::AppUtils;
7 use OpenILS::Utils::CStoreEditor qw/:funcs/;
10 $Data::Dumper::Indent = 0;
11 my $U = 'OpenILS::Application::AppUtils';
17 $ctx->{register} = {};
18 $self->collect_register_validation_settings;
19 $self->collect_requestor_info;
21 # in the home org unit selector, we only want to present
22 # org units to the patron which support self-registration.
23 # all other org units will be disabled
24 $ctx->{register}{valid_orgs} =
25 $self->setting_is_true_for_orgs('opac.allow_pending_user');
27 $self->collect_opt_in_settings;
29 # just loading the form
30 return Apache2::Const::OK
31 unless $cgi->request_method eq 'POST';
33 my $user = Fieldmapper::staging::user_stage->new;
34 my $addr = Fieldmapper::staging::mailing_address_stage->new;
37 foreach (grep /^stgu\./, $cgi->param) {
38 my $val = $cgi->param($_);
39 $self->inspect_register_value($_, $val);
44 # requestor is logged in, capture who is making this request
45 $user->requesting_usr($ctx->{user}->id) if $ctx->{user};
47 # make sure the selected home org unit is in the list
48 # of valid orgs. This can happen if the selector
49 # defaults to CONS, for example.
50 $ctx->{register}{invalid}{bad_home_ou} = 1 unless
51 grep {$_ eq $user->home_ou} @{$ctx->{register}{valid_orgs}};
55 foreach (grep /^stgma\./, $cgi->param) {
56 my $val = $cgi->param($_);
57 $self->inspect_register_value($_, $val);
63 # if the form contains no address fields, do not
64 # attempt to create a pending address
65 $addr = undef unless $has_addr;
69 foreach (grep /^stgs\./, $cgi->param) {
70 my $val = $cgi->param($_);
71 next unless $val; # opt-in settings are always Boolean,
72 # so just skip if not set
73 $self->inspect_register_value($_, $val);
75 my $setting = Fieldmapper::staging::setting_stage->new;
76 $setting->setting($_);
77 $setting->value('true');
78 push @$settings, $setting;
81 # At least one value was invalid. Exit early and re-render.
82 return Apache2::Const::OK if $ctx->{register}{invalid};
84 $self->test_requested_username($user);
86 # user.stage.create will generate a temporary usrname and
87 # link the user and address objects via this username in the DB.
88 my $resp = $U->simplereq(
90 'open-ils.actor.user.stage.create',
91 $user, $addr, undef, [], $settings
94 if (!$resp or ref $resp) {
96 $logger->warn("Patron self-reg failed ".Dumper($resp));
97 $ctx->{register}{error} = 1;
101 $logger->info("Patron self-reg success; usrname $resp");
102 $ctx->{register}{success} = 1;
105 return Apache2::Const::OK;
108 # if the pending account is requested by an existing user account,
109 # load the existing user's data to pre-populate some fields.
110 sub collect_requestor_info {
112 return unless $self->ctx->{user};
114 my $user = $self->editor->retrieve_actor_user([
115 $self->ctx->{user}->id,
116 {flesh => 1, flesh_fields => {
117 au => [qw/mailing_address billing_address/]}
122 my $vhash = $self->ctx->{register}{values} = {};
123 my $addr = $user->mailing_address || $user->billing_address;
124 $vhash->{stgu}{home_ou} = $user->home_ou;
127 $vhash->{stgma}{city} = $addr->city;
128 $vhash->{stgma}{county} = $addr->county;
129 $vhash->{stgma}{state} = $addr->state;
130 $vhash->{stgma}{post_code} = $addr->post_code;
134 sub collect_opt_in_settings {
136 my $e = $self->editor;
138 my $types = $e->json_query({
139 select => {cust => ['name']},
140 from => {atevdef => 'cust'},
141 transform => 'distinct',
144 owner => [ map { $_ } @{ $self->ctx->{register}{valid_orgs} } ],
149 $self->ctx->{register}{opt_in_settings} =
150 $e->search_config_usr_setting_type({name => [map {$_->{name}} @$types]});
153 # if the username is in use by an actor.usr OR a
154 # pending user treat it as taken and warn the user.
155 sub test_requested_username {
156 my ($self, $user) = @_;
157 my $uname = $user->usrname || return;
158 my $e = $self->editor;
160 my $taken = $e->search_actor_user(
161 {usrname => $uname, deleted => 'f'},
165 $taken = $e->search_staging_user_stage(
168 )->[0] unless $taken;
171 $self->ctx->{register}{username_taken} = 1;
172 $user->clear_usrname;
176 sub collect_register_validation_settings {
178 my $ctx = $self->ctx;
179 my $e = new_editor();
180 my $ctx_org = $ctx->{physical_loc} || $self->_get_search_lib;
181 my $shash = $self->{register}{settings} = {};
183 # retrieve the org unit setting types and values
184 # that are relevant to our validation tasks.
186 my $settings = $e->json_query({
187 select => {coust => ['name']},
189 where => {name => {like => 'ui.patron.edit.%.%.%'}}
192 # load org setting values for all of the regex,
193 # example, show, and require settings
194 for my $set (@$settings) {
196 next unless $set =~ /regex$|show$|require$|example$/;
198 my $val = $ctx->{get_org_setting}->($ctx_org, $set);
199 next unless $val; # no configured org setting
201 # extract the field class, name, and
202 # setting type from the setting name
203 my (undef, undef, undef, $cls, $field, $type) = split(/\./, $set);
205 # translate classes into stage classes
206 my $scls = ($cls eq 'au') ? 'stgu' : 'stgma';
208 $shash->{$scls}{$field}{$type} = $val;
211 # use the generic phone settings where none are provided for day_phone.
213 $shash->{stgu}{day_phone}{example} =
214 $ctx->{get_org_setting}->($ctx_org, 'ui.patron.edit.phone.example')
215 unless $shash->{stgu}{day_phone}{example};
217 $shash->{stgu}{day_phone}{regex} =
218 $ctx->{get_org_setting}->($ctx_org, 'ui.patron.edit.phone.regex')
219 unless $shash->{stgu}{day_phone}{regex};
221 # The regex OUS for username does not match the format of the other
222 # org settings. Wrangle it into place.
223 $shash->{stgu}{usrname}{regex} =
224 $ctx->{get_org_setting}->($ctx_org, 'opac.username_regex');
226 # some fields are assumed to be visible / required even without the
227 # presence of org unit settings. E.g. we obviously want the user to
228 # enter a name, since a name is required for ultimately creating a user
229 # account. We can mimic that by forcing some org unit setting values
231 $shash->{stgu}{first_given_name}{require} = 1
232 unless defined $shash->{stgu}{first_given_name}{require};
233 $shash->{stgu}{second_given_name}{show} = 1
234 unless defined $shash->{stgu}{second_given_name}{show};
235 $shash->{stgu}{family_name}{require} = 1
236 unless defined $shash->{stgu}{family_name}{require};
237 $shash->{stgma}{street1}{require} = 1
238 unless defined $shash->{stgma}{street1}{require};
239 $shash->{stgma}{street2}{show} = 1
240 unless defined $shash->{stgma}{street2}{show};
241 $shash->{stgma}{city}{require} = 1
242 unless defined $shash->{stgma}{city}{require};
243 $shash->{stgma}{post_code}{require} = 1
244 unless defined $shash->{stgma}{post_code}{require};
245 $shash->{stgu}{usrname}{show} = 1
246 unless defined $shash->{stgu}{usrname}{show};
248 $ctx->{register}{settings} = $shash;
250 # laod the page timeout setting
251 $shash->{refresh_timeout} =
252 $ctx->{get_org_setting}->($ctx_org, 'opac.self_register.timeout');
255 # inspects each value and determines, based on org unit settings,
256 # if the value is invalid. Invalid is defined as not providing
257 # a value when one is required or not matching the configured regex.
258 sub inspect_register_value {
259 my ($self, $field_path, $value) = @_;
260 my $ctx = $self->ctx;
261 my ($scls, $field) = split(/\./, $field_path, 2);
263 if ($scls eq 'stgs') {
265 foreach my $type (@{ $self->ctx->{register}{opt_in_settings} }) {
266 if ($field eq $type->name) {
271 $ctx->{register}{invalid}{$scls}{$field}{invalid} = 1;
272 $logger->info("patron register: trying to set an opt-in ".
273 "setting $field that is not allowed.");
280 if ($self->{register}{settings}{$scls}{$field}{require}) {
281 $ctx->{register}{invalid}{$scls}{$field}{require} = 1;
283 $logger->info("patron register field $field ".
284 "requires a value, but none was entered");
289 my $regex = $self->{register}{settings}{$scls}{$field}{regex};
290 return if !$regex or $value =~ /$regex/; # field is valid
292 $logger->info("invalid value was provided for patron ".
293 "register field=$field; pattern=$regex; value=$value");
295 $ctx->{register}{invalid}{$scls}{$field}{regex} = 1;