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");
121 $sth->execute or die $sth->errstr;
122 $confcount = $sth->fetchrow_arrayref->[0];
128 warn "NO CONFIGURATION RECORDS FOUND";
131 unless ( $callback_hack ) {
132 warn "$me calling callbacks\n" if $DEBUG;
133 foreach ( keys %callback ) {
135 # breaks multi-database installs # delete $callback{$_}; #run once
138 &{$_} foreach @callback;
140 warn "$me skipping callbacks (callback_hack set)\n" if $DEBUG;
143 warn "$me forksuidsetup loading user\n" if $DEBUG;
144 FS::CurrentUser->load_user($user);
150 DBI->connect( getsecrets(@_), { 'AutoCommit' => 0,
152 'ShowErrorStatement' => 1,
155 or die "DBI->connect error: $DBI::errstr\n";
158 =item install_callback
160 A package can install a callback to be run in adminsuidsetup by passing
161 a coderef to the FS::UID->install_callback class method. If adminsuidsetup has
162 run already, the callback will also be run immediately.
164 $coderef = sub { warn "Hi, I'm returning your call!" };
165 FS::UID->install_callback($coderef);
167 install_callback FS::UID sub {
168 warn "Hi, I'm returning your call!"
173 sub install_callback {
175 my $callback = shift;
176 push @callback, $callback;
177 &{$callback} if $dbh;
180 =item cgisuidsetup CGI_object
182 Takes a single argument, which is a CGI (see L<CGI>) or Apache (see L<Apache>)
183 object (CGI::Base is depriciated). Runs cgisetotaker and then adminsuidsetup.
189 if ( $cgi->isa('CGI::Base') ) {
190 carp "Use of CGI::Base is depriciated";
191 } elsif ( $cgi->isa('Apache') ) {
193 } elsif ( ! $cgi->isa('CGI') ) {
194 croak "fatal: unrecognized object $cgi";
197 adminsuidsetup($user);
202 Returns the CGI (see L<CGI>) object.
207 carp "warning: \$FS::UID::cgi isa Apache" if $cgi->isa('Apache');
213 Returns the DBI database handle.
223 Returns the DBI data source.
233 Returns just the driver name portion of the DBI data source.
238 return $driver_name if defined $driver_name;
239 $driver_name = ( split(':', $datasrc) )[1];
243 croak "suidsetup depriciated";
248 Returns the current Freeside user.
258 Sets and returns the CGI REMOTE_USER. $cgi should be defined as a CGI.pm
259 object (see L<CGI>) or an Apache object (see L<Apache>). Support for CGI::Base
260 and derived classes is depriciated.
265 if ( $cgi && $cgi->isa('CGI::Base') && defined $cgi->var('REMOTE_USER')) {
266 carp "Use of CGI::Base is depriciated";
267 $user = lc ( $cgi->var('REMOTE_USER') );
268 } elsif ( $cgi && $cgi->isa('CGI') && defined $cgi->remote_user ) {
269 $user = lc ( $cgi->remote_user );
270 } elsif ( $cgi && $cgi->isa('Apache') ) {
271 $user = lc ( $cgi->connection->user );
273 die "fatal: Can't get REMOTE_USER! for cgi $cgi - you need to setup ".
274 "Apache user authentication as documented in httemplate/docs/install.html";
281 Returns true if effective UID is that of the freeside user.
286 ( $> == $freeside_uid );
291 Returns true if the real UID is that of the freeside user.
296 ( $< == $freeside_uid );
299 =item getsecrets [ USER ]
301 Sets the user to USER, if supplied.
302 Sets and returns the DBI datasource, username and password for this user from
303 the `/usr/local/etc/freeside/mapsecrets' file.
308 my($setuser) = shift;
309 $user = $setuser if $setuser;
311 if ( -e "$conf_dir/mapsecrets" ) {
312 die "No user!" unless $user;
313 my($line) = grep /^\s*($user|\*)\s/,
314 map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/mapsecrets");
315 confess "User $user not found in mapsecrets!" unless $line;
316 $line =~ /^\s*($user|\*)\s+(.*)$/;
318 die "Illegal mapsecrets line for user?!" unless $secrets;
320 # no mapsecrets file at all, so do the default thing
321 $secrets = 'secrets';
324 ($datasrc, $db_user, $db_pass) =
325 map { /^(.*)$/; $1 } readline(new IO::File "$conf_dir/$secrets")
326 or die "Can't get secrets: $conf_dir/$secrets: $!\n";
328 ($datasrc, $db_user, $db_pass);
333 Returns true whenever we should use 1.7 configuration compatibility.
345 Warning: this interface is (still) likely to change in future releases.
347 New (experimental) callback interface:
349 A package can install a callback to be run in adminsuidsetup by passing
350 a coderef to the FS::UID->install_callback class method. If adminsuidsetup has
351 run already, the callback will also be run immediately.
353 $coderef = sub { warn "Hi, I'm returning your call!" };
354 FS::UID->install_callback($coderef);
356 install_callback FS::UID sub {
357 warn "Hi, I'm returning your call!"
360 Old (deprecated) callback interface:
362 A package can install a callback to be run in adminsuidsetup by putting a
363 coderef into the hash %FS::UID::callback :
365 $coderef = sub { warn "Hi, I'm returning your call!" };
366 $FS::UID::callback{'Package::Name'} = $coderef;
370 Too many package-global variables.
374 No capabilities yet. When mod_perl and Authen::DBI are implemented,
375 cgisuidsetup will go away as well.
377 Goes through contortions to support non-OO syntax with multiple datasrc's.
379 Callbacks are (still) inelegant.
383 L<FS::Record>, L<CGI>, L<DBI>, config.html from the base documentation.