5 @ISA @EXPORT_OK $DEBUG $me $cgi $dbh $freeside_uid $user
6 $conf_dir $secrets $datasrc $db_user $db_pass %callback @callback
7 $driver_name $AutoCommit $callback_hack $use_confcompat
10 getsecrets cgisetotaker
13 use Carp qw(carp croak cluck confess);
19 @EXPORT_OK = qw(checkeuid checkruid cgisuidsetup adminsuidsetup forksuidsetup
20 getotaker dbh datasrc getsecrets driver_name myconnect
26 $freeside_uid = scalar(getpwnam('freeside'));
28 $conf_dir = "%%%FREESIDE_CONF%%%";
30 $AutoCommit = 1; #ours, not DBI
36 FS::UID - Subroutines for database login and assorted other stuff
40 use FS::UID qw(adminsuidsetup cgisuidsetup dbh datasrc getotaker
46 $dbh = cgisuidsetup($cgi);
52 $driver_name = driver_name;
56 Provides a hodgepodge of subroutines.
62 =item adminsuidsetup USER
64 Sets the user to USER (see config.html from the base documentation).
65 Cleans the environment.
66 Make sure the script is running as freeside, or setuid freeside.
67 Opens a connection to the database.
68 Swaps real and effective UIDs.
69 Runs any defined callbacks (see below).
70 Returns the DBI database handle (usually you don't need this).
75 $dbh->disconnect if $dbh;
82 warn "$me forksuidsetup starting for $user\n" if $DEBUG;
84 if ( $FS::CurrentUser::upgrade_hack ) {
85 $user = 'fs_bootstrap';
87 croak "fatal: adminsuidsetup called without arguements" unless $user;
89 $user =~ /^([\w\-\.]+)$/ or croak "fatal: illegal user $user";
93 $ENV{'PATH'} ='/usr/local/bin:/usr/bin:/usr/ucb:/bin';
94 $ENV{'SHELL'} = '/bin/sh';
95 $ENV{'IFS'} = " \t\n";
98 $ENV{'BASH_ENV'} = '';
100 croak "Not running uid freeside!" unless checkeuid();
102 warn "$me forksuidsetup connecting to database\n" if $DEBUG;
103 if ( $FS::CurrentUser::upgrade_hack && $olduser ) {
104 $dbh = &myconnect($olduser);
108 warn "$me forksuidsetup connected to database with handle $dbh\n" if $DEBUG;
110 warn "$me forksuidsetup loading schema\n" if $DEBUG;
111 use FS::Schema qw(reload_dbdef dbdef);
112 reload_dbdef("$conf_dir/dbdef.$datasrc")
113 unless $FS::Schema::setup_hack;
115 warn "$me forksuidsetup deciding upon config system to use\n" if $DEBUG;
118 if ( dbdef->table('conf')
119 and $sth = $dbh->prepare("SELECT COUNT(*) FROM conf")
124 my $confcount = $sth->fetchrow_arrayref->[0];
129 warn "NO CONFIGURATION RECORDS FOUND";
133 warn "NO CONFIGURATION TABLE FOUND";
136 unless ( $callback_hack ) {
137 warn "$me calling callbacks\n" if $DEBUG;
138 foreach ( keys %callback ) {
140 # breaks multi-database installs # delete $callback{$_}; #run once
143 &{$_} foreach @callback;
145 warn "$me skipping callbacks (callback_hack set)\n" if $DEBUG;
148 warn "$me forksuidsetup loading user\n" if $DEBUG;
149 FS::CurrentUser->load_user($user);
155 DBI->connect( getsecrets(@_), { 'AutoCommit' => 0,
157 'ShowErrorStatement' => 1,
160 or die "DBI->connect error: $DBI::errstr\n";
163 =item install_callback
165 A package can install a callback to be run in adminsuidsetup by passing
166 a coderef to the FS::UID->install_callback class method. If adminsuidsetup has
167 run already, the callback will also be run immediately.
169 $coderef = sub { warn "Hi, I'm returning your call!" };
170 FS::UID->install_callback($coderef);
172 install_callback FS::UID sub {
173 warn "Hi, I'm returning your call!"
178 sub install_callback {
180 my $callback = shift;
181 push @callback, $callback;
182 &{$callback} if $dbh;
185 =item cgisuidsetup CGI_object
187 Takes a single argument, which is a CGI (see L<CGI>) or Apache (see L<Apache>)
188 object (CGI::Base is depriciated). Runs cgisetotaker and then adminsuidsetup.
194 if ( $cgi->isa('CGI::Base') ) {
195 carp "Use of CGI::Base is depriciated";
196 } elsif ( $cgi->isa('Apache') ) {
198 } elsif ( ! $cgi->isa('CGI') ) {
199 croak "fatal: unrecognized object $cgi";
202 adminsuidsetup($user);
207 Returns the CGI (see L<CGI>) object.
212 carp "warning: \$FS::UID::cgi isa Apache" if $cgi->isa('Apache');
218 Returns the DBI database handle.
228 Returns the DBI data source.
238 Returns just the driver name portion of the DBI data source.
243 return $driver_name if defined $driver_name;
244 $driver_name = ( split(':', $datasrc) )[1];
248 croak "suidsetup depriciated";
253 Returns the current Freeside user.
263 Sets and returns the CGI REMOTE_USER. $cgi should be defined as a CGI.pm
264 object (see L<CGI>) or an Apache object (see L<Apache>). Support for CGI::Base
265 and derived classes is depriciated.
270 if ( $cgi && $cgi->isa('CGI::Base') && defined $cgi->var('REMOTE_USER')) {
271 carp "Use of CGI::Base is depriciated";
272 $user = lc ( $cgi->var('REMOTE_USER') );
273 } elsif ( $cgi && $cgi->isa('CGI') && defined $cgi->remote_user ) {
274 $user = lc ( $cgi->remote_user );
275 } elsif ( $cgi && $cgi->isa('Apache') ) {
276 $user = lc ( $cgi->connection->user );
278 die "fatal: Can't get REMOTE_USER! for cgi $cgi - you need to setup ".
279 "Apache user authentication as documented in httemplate/docs/install.html";
286 Returns true if effective UID is that of the freeside user.
291 ( $> == $freeside_uid );
296 Returns true if the real UID is that of the freeside user.
301 ( $< == $freeside_uid );
304 =item getsecrets [ USER ]
306 Sets the user to USER, if supplied.
307 Sets and returns the DBI datasource, username and password for this user from
308 the `/usr/local/etc/freeside/mapsecrets' file.
313 my($setuser) = shift;
314 $user = $setuser if $setuser;
316 if ( -e "$conf_dir/mapsecrets" ) {
317 die "No user!" unless $user;
318 my($line) = grep /^\s*($user|\*)\s/,
319 map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/mapsecrets");
320 confess "User $user not found in mapsecrets!" unless $line;
321 $line =~ /^\s*($user|\*)\s+(.*)$/;
323 die "Illegal mapsecrets line for user?!" unless $secrets;
325 # no mapsecrets file at all, so do the default thing
326 $secrets = 'secrets';
329 ($datasrc, $db_user, $db_pass) =
330 map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/$secrets")
331 or die "Can't get secrets: $conf_dir/$secrets: $!\n";
333 ($datasrc, $db_user, $db_pass);
338 Returns true whenever we should use 1.7 configuration compatibility.
350 Warning: this interface is (still) likely to change in future releases.
352 New (experimental) callback interface:
354 A package can install a callback to be run in adminsuidsetup by passing
355 a coderef to the FS::UID->install_callback class method. If adminsuidsetup has
356 run already, the callback will also be run immediately.
358 $coderef = sub { warn "Hi, I'm returning your call!" };
359 FS::UID->install_callback($coderef);
361 install_callback FS::UID sub {
362 warn "Hi, I'm returning your call!"
365 Old (deprecated) callback interface:
367 A package can install a callback to be run in adminsuidsetup by putting a
368 coderef into the hash %FS::UID::callback :
370 $coderef = sub { warn "Hi, I'm returning your call!" };
371 $FS::UID::callback{'Package::Name'} = $coderef;
375 Too many package-global variables.
379 No capabilities yet. When mod_perl and Authen::DBI are implemented,
380 cgisuidsetup will go away as well.
382 Goes through contortions to support non-OO syntax with multiple datasrc's.
384 Callbacks are (still) inelegant.
388 L<FS::Record>, L<CGI>, L<DBI>, config.html from the base documentation.