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);
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;
119 my $sth = $dbh->prepare("SELECT COUNT(*) FROM conf") or warn $dbh->errstr;
120 $sth and $sth->execute or warn $sth->errstr;
121 $sth and $confcount = $sth->fetchrow_arrayref->[0];
126 warn "NO CONFIGURATION RECORDS FOUND";
129 unless ( $callback_hack ) {
130 warn "$me calling callbacks\n" if $DEBUG;
131 foreach ( keys %callback ) {
133 # breaks multi-database installs # delete $callback{$_}; #run once
136 &{$_} foreach @callback;
138 warn "$me skipping callbacks (callback_hack set)\n" if $DEBUG;
141 warn "$me forksuidsetup loading user\n" if $DEBUG;
142 FS::CurrentUser->load_user($user);
148 DBI->connect( getsecrets(@_), { 'AutoCommit' => 0,
150 'ShowErrorStatement' => 1,
153 or die "DBI->connect error: $DBI::errstr\n";
156 =item install_callback
158 A package can install a callback to be run in adminsuidsetup by passing
159 a coderef to the FS::UID->install_callback class method. If adminsuidsetup has
160 run already, the callback will also be run immediately.
162 $coderef = sub { warn "Hi, I'm returning your call!" };
163 FS::UID->install_callback($coderef);
165 install_callback FS::UID sub {
166 warn "Hi, I'm returning your call!"
171 sub install_callback {
173 my $callback = shift;
174 push @callback, $callback;
175 &{$callback} if $dbh;
178 =item cgisuidsetup CGI_object
180 Takes a single argument, which is a CGI (see L<CGI>) or Apache (see L<Apache>)
181 object (CGI::Base is depriciated). Runs cgisetotaker and then adminsuidsetup.
187 if ( $cgi->isa('CGI::Base') ) {
188 carp "Use of CGI::Base is depriciated";
189 } elsif ( $cgi->isa('Apache') ) {
191 } elsif ( ! $cgi->isa('CGI') ) {
192 croak "fatal: unrecognized object $cgi";
195 adminsuidsetup($user);
200 Returns the CGI (see L<CGI>) object.
205 carp "warning: \$FS::UID::cgi isa Apache" if $cgi->isa('Apache');
211 Returns the DBI database handle.
221 Returns the DBI data source.
231 Returns just the driver name portion of the DBI data source.
236 return $driver_name if defined $driver_name;
237 $driver_name = ( split(':', $datasrc) )[1];
241 croak "suidsetup depriciated";
246 Returns the current Freeside user.
256 Sets and returns the CGI REMOTE_USER. $cgi should be defined as a CGI.pm
257 object (see L<CGI>) or an Apache object (see L<Apache>). Support for CGI::Base
258 and derived classes is depriciated.
263 if ( $cgi && $cgi->isa('CGI::Base') && defined $cgi->var('REMOTE_USER')) {
264 carp "Use of CGI::Base is depriciated";
265 $user = lc ( $cgi->var('REMOTE_USER') );
266 } elsif ( $cgi && $cgi->isa('CGI') && defined $cgi->remote_user ) {
267 $user = lc ( $cgi->remote_user );
268 } elsif ( $cgi && $cgi->isa('Apache') ) {
269 $user = lc ( $cgi->connection->user );
271 die "fatal: Can't get REMOTE_USER! for cgi $cgi - you need to setup ".
272 "Apache user authentication as documented in httemplate/docs/install.html";
279 Returns true if effective UID is that of the freeside user.
284 ( $> == $freeside_uid );
289 Returns true if the real UID is that of the freeside user.
294 ( $< == $freeside_uid );
297 =item getsecrets [ USER ]
299 Sets the user to USER, if supplied.
300 Sets and returns the DBI datasource, username and password for this user from
301 the `/usr/local/etc/freeside/mapsecrets' file.
306 my($setuser) = shift;
307 $user = $setuser if $setuser;
309 if ( -e "$conf_dir/mapsecrets" ) {
310 die "No user!" unless $user;
311 my($line) = grep /^\s*($user|\*)\s/,
312 map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/mapsecrets");
313 confess "User $user not found in mapsecrets!" unless $line;
314 $line =~ /^\s*($user|\*)\s+(.*)$/;
316 die "Illegal mapsecrets line for user?!" unless $secrets;
318 # no mapsecrets file at all, so do the default thing
319 $secrets = 'secrets';
322 ($datasrc, $db_user, $db_pass) =
323 map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/$secrets")
324 or die "Can't get secrets: $conf_dir/$secrets: $!\n";
326 ($datasrc, $db_user, $db_pass);
331 Returns true whenever we should use 1.7 configuration compatibility.
343 Warning: this interface is (still) likely to change in future releases.
345 New (experimental) callback interface:
347 A package can install a callback to be run in adminsuidsetup by passing
348 a coderef to the FS::UID->install_callback class method. If adminsuidsetup has
349 run already, the callback will also be run immediately.
351 $coderef = sub { warn "Hi, I'm returning your call!" };
352 FS::UID->install_callback($coderef);
354 install_callback FS::UID sub {
355 warn "Hi, I'm returning your call!"
358 Old (deprecated) callback interface:
360 A package can install a callback to be run in adminsuidsetup by putting a
361 coderef into the hash %FS::UID::callback :
363 $coderef = sub { warn "Hi, I'm returning your call!" };
364 $FS::UID::callback{'Package::Name'} = $coderef;
368 Too many package-global variables.
372 No capabilities yet. When mod_perl and Authen::DBI are implemented,
373 cgisuidsetup will go away as well.
375 Goes through contortions to support non-OO syntax with multiple datasrc's.
377 Callbacks are (still) inelegant.
381 L<FS::Record>, L<CGI>, L<DBI>, config.html from the base documentation.