package RideLogicAPIQueryWrapper; use strict; use RideLogic (); use RideLogicDBI; use POSIX; require RideLogic ; require RideLogicDBI; require Exporter; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = "0.01"; @ISA = qw( Exporter RideLogicDBI ); @EXPORT = qw( ); @EXPORT_OK = qw( ); %EXPORT_TAGS = ( DEFAULT => [ qw( ) ] ); my $PACKAGE_NAME = "RideLogicAPIQueryWrapper"; my $DEFAULT_GROUP_NAME = "ORG"; # our constructor sub connect { my $class = shift; my $r = $class->RideLogicDBI::connect(@_); # default to raising an error if (!defined($_[3])) { my $dbh = ${$r->{'dbh_ref'}}; } return $r; } ################################################### sub unix_to_readable_time { my $unix_time = shift; my @a = ( $unix_time ? localtime($unix_time) : localtime() ); return sprintf('%d-%02d-%02d %02d:%02d:%02d', (1900+$a[5]), (1+$a[4]), $a[3], $a[2], $a[1], $a[0]); } sub audit_users_start { my $self = shift; my $id = shift; my $comment = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_users_start($dbh, $id, $comment); } sub audit_users_end { my $self = shift; my $id = shift; my $audit_id = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_users_end($dbh, $id, $audit_id); } sub audit_admins_start { my $self = shift; my $id = shift; my $comment = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_admins_start($dbh, $id, $comment); } sub audit_admins_end { my $self = shift; my $id = shift; my $audit_id = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_admins_end($dbh, $id, $audit_id); } sub audit_user_card_start { my $self = shift; my $id = shift; my $comment = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_user_card_start($dbh, $id, $comment); } sub audit_user_card_end { my $self = shift; my $id = shift; my $audit_id = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_user_card_end($dbh, $id, $audit_id); } sub audit_user_pass_start { my $self = shift; my $id = shift; my $comment = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_user_pass_start($dbh, $id, $comment); } sub audit_user_pass_end { my $self = shift; my $id = shift; my $audit_id = shift; my $dbh = ${$self->{'dbh_ref'}}; return RideLogic::audit_user_pass_end($dbh, $id, $audit_id); } ##################### # Helper functions ##################### sub gen_token { my $len = shift; my ($r, $tok); my @a = qw(0 1 2 3 4 5 6 7 8 9 a b c d e f); open R, "/dev/urandom"; read(R, $r, $len/2); close R; my @r = split(//, $r); for (my $i=0; $i<$len/2; $i++) { $tok .= $a[ord($r[$i]) >> 4]; $tok .= $a[ord($r[$i]) & 0xf]; } return $tok; } #################################################### sub initiate_session { my $self = shift; my $srv_tok = shift; my $usr_tok = shift; my $ip = shift; my $dbh = ${$self->{'dbh_ref'}}; $dbh->begin_work(); my $q = $self->prepare("insert into org_api_session (timestamp, server_token, user_token, ip, active) values ( now(), ?, ?, ?, 1)"); $q->execute($srv_tok, $usr_tok, $ip) || return 0; $dbh->commit(); return 1; } #################################################### sub get_api_server_session_age { my $self = shift; my $pass = shift; my $tok = shift; my $ip = shift; my ($query, $result); my $dbh = ${$self->{'dbh_ref'}}; $query = $dbh->prepare("select time_to_sec( timediff( now(), timestamp)) sec, server_token, user_token, ip, active from org_api_session where active = 1 and ip = ? and sha1( concat( ? , server_token )) = ? limit 1"); $result = $query->execute($ip, $pass, $tok); my $row = $query->fetchrow_hashref; return -1 if (!$row); return $row->{'sec'}; } #################################################### sub get_api_user_session_age { my $self = shift; my $pass = shift; my $tok = shift; my $ip = shift; my ($query, $result); my $dbh = ${$self->{'dbh_ref'}}; $query = $self->prepare("select time_to_sec( timediff( now(), timestamp)) sec, server_token, user_token, ip, active from org_api_session where active = 1 and ip = ? and sha1( concat( ? , user_token )) = ? limit 1"); $result = $query->execute($ip, $pass, $tok); my $row = $query->fetchrow_hashref; return -1 if (!$row); return $row->{'sec'}; } #################################################### sub deactivate_session { my $self = shift; my $pass = shift; my $tok = shift; my $ip = shift; my ($query, $result); my $dbh = ${$self->{'dbh_ref'}}; $query = $self->prepare("update org_api_session set active = 0 where ip = ? and active = 1 and sha1(concat(?,server_token)) = ?"); $result = $query->execute($ip, $pass, $tok); } #################################################### #################################################### sub set_user_reset_attempts { my $self = shift; my $user_id = shift; my $n = shift; my ($query, $result); my $dbh = ${$self->{'dbh_ref'}}; my $audit_id = $self->audit_users_start($dbh, $user_id, "RideLogicAPIQueryWrapper::set_user_reset_attempts : updating reset attempts"); $query = $self->prepare("update users set reset_attempts = ? where userid = ?"); $result = $query->execute($n, $user_id); $self->audit_users_end($dbh, $user_id, $audit_id); } #################################################### sub update_user_reset_attempts { my $self = shift; my $user_id = shift; my ($query, $result); my $dbh = ${$self->{'dbh_ref'}}; $dbh->begin_work(); my $audit_id = $self->audit_users_start($dbh, $user_id, "ridelogic_web_api: updating reset attempts"); $query = $self->prepare("update users set reset_attempts = 0 where userid = ?"); $result = $query->execute($user_id); $self->audit_users_end($dbh, $user_id, $audit_id); $dbh->commit(); } ########################## # # ... # ########################## sub create_register_email { my $self = shift; my $registration_token = shift; my $email = shift; my $FUNC_NAME = "create_register_email"; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # $self->begin_work(); $query = $self->prepare("insert into org_api_register_email (timestamp, token, active, email) values ( now() , ?, ?, ?)"); $result = $query->execute( $registration_token, 1, $email); # $self->commit(); $self->unlock_commit() if $lock_local; return 1; } sub get_register_email_info { my $self = shift; my $registration_token = shift; my $FUNC_NAME = "get_register_email_info"; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select timestamp, token, time_to_sec(timediff(now(), timestamp)) sec, email from org_api_register_email where token = ? and active = 1 limit 1"); $result = $query->execute( $registration_token ); $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return (-1, undef); } my ($sec, $email) = ($row->[2], $row->[3]); $self->unlock_commit() if $lock_local; return ($row->[2], $row->[3]); } #################################################### sub deactivate_register_email { my $self = shift; my $registration_token = shift; my $FUNC_NAME = "deactivate_register_email"; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("update org_api_register_email set active = 0 where token = ?"); $result = $query->execute($registration_token); $self->unlock_commit() if $lock_local; return 1; } #################################################### sub insert_password_reset { my $self = shift; my $token = shift; my $userid = shift; my $email = shift; my $FUNC_NAME = "insert_password_reset"; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("insert into org_api_password_reset (timestamp, token, userid, email, active) values ( now() , ?, ?, ?, 1)"); $result = $query->execute( $token, $userid, $email ); $self->unlock_commit() if $lock_local; return 1; } ########## sub deactivate_stale_password_resets { my $self = shift; my $token = shift; my $userid = shift; my $FUNC_NAME = "deactivate_stale_password_resets"; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("update org_api_password_reset set active = 0 where userid = ? and token != ?"); $result = $query->execute( $userid, $token ); $self->unlock_commit() if $lock_local; return 1; } ########## sub increment_user_reset_attempts { my $self = shift; my $userid = shift; my $FUNC_NAME = "increment_user_reset_attempts"; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my %thash; my $r = $self->GetUser(\%thash, { UserId => $userid } ); if (!$r) { $self->unlock_rollback() if $lock_local; return undef; } my $new_reset_attempts = $thash{ResetAttempts}+1; %thash = (); $r = $self->SetUser( \%thash, { UserId => $userid, ResetAttempts => $new_reset_attempts } ); if (!$r) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return 1; } ########## sub get_password_reset_request_age { my $self = shift; my $tok = shift; my $FUNC_NAME = 'get_password_reset_request_age'; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select time_to_sec(timediff(now(), timestamp)) sec from org_api_password_reset where token = ? and active = 1 order by timestamp desc limit 1"); $result = $query->execute($tok); $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return $row->[0]; } ########## sub get_password_reset_request_user_id { my $self = shift; my $tok = shift; my $FUNC_NAME = 'get_password_reset_request_user_id'; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select userid from org_api_password_reset where token = ? and active = 1 order by timestamp desc limit 1"); $result = $query->execute($tok); $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return $row->[0]; } ########## sub deactivate_password_reset_for_user { my $self = shift; my $userid = shift; my $FUNC_NAME = 'deactivate_password_reset'; my ($query, $r); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("update org_api_password_reset set active = 0 where userid = ? "); $r = $query->execute( $userid ); $self->unlock_commit() if $lock_local; } ########## my %function_locked_table_map = ( '_common' => { 'user_card' => 'w', 'user_pass' => 'w', 'active_rider_table' => 'w', 'audit_user_pass' => 'w', 'audit_user_card' => 'w', 'org_card_order_queue' => 'w', 'diagnostic_log' => 'w', 'groups' => 'r', 'users' => 'r', 'admins' => 'r', 'rule_class' => 'r', 'rule_mappings' => 'r', 'org_api_session' => 'w', 'org_default_card_value' => 'r', 'org_default_pass_value' => 'r' }, # inhered from common 'GetCard' => '_common', 'GetCards' => '_common', 'IssueBlankCard' => '_common', 'AddCard' => '_common', 'TransferCard' => '_common', 'RemoveCard' => '_common', 'GetPendingQueueCard' => '_common', 'ProcessPendingQueue' => '_common', 'RemovePendingQueue' => '_common', 'insert_active_rider_table' => '_common', 'CreateCard' => '_common', 'RemovePass' => '_common', 'TransferPass' => '_common', 'AddPass' => '_common', # explicit 'get_user_id' => { 'users' => 'r' , 'groups' => 'r' } , 'CreateUser' => { 'users' => 'w', 'audit_users' => 'w' , 'groups' => 'r' } , 'RemoveUser' => { 'users' => 'w', 'user_card' => 'w', 'audit_users' => 'w' , 'audit_user_card' => 'w', 'groups' => 'r' } , 'GetUser' => { 'users' => 'r' , 'groups' => 'r' } , 'SetUser' => { 'users' => 'w', 'audit_users' => 'w' , 'groups' => 'r' } , 'username_exists' => { 'users' => 'r' } , 'valid_user' => { 'users' => 'r' } , 'get_default_mag_track' => { 'org_default_card_value' => 'r' } , 'get_default_rflength' => { 'org_default_card_value' => 'r' } , 'get_default_rfsite' => { 'org_default_card_value' => 'r' } , 'construct_mag_token' => { 'org_default_card_value' => 'r' } , 'construct_rfid_token' => { 'org_default_card_value' => 'r' } , 'construct_user_card_credential_match' => { 'org_default_card_value' => 'r', 'groups' => 'r' } , 'update_user_card' => { 'audit_user_card' => 'w', 'user_card' => 'w' } , 'GetDefaultCardGroupInfo' => { 'groups' => 'r' } , 'get_group_name' => { 'groups' => 'r' } , 'get_user_pass_group_name' => { 'user_card' => 'r', 'user_pass' => 'r', 'groups' => 'r' } , 'get_admin_group_name' => { 'groups' => 'r', 'admins' => 'r' } , 'get_group_id' => { 'groups' => 'r' } , # 'get_entry_group_name' => { 'groups' => 'r', $table => 'r' } , 'disassociate_user_from_card' => { 'audit_user_card' => 'w', 'user_card' => 'w' } , 'associate_user_to_card' => { 'audit_user_card' => 'w', 'user_card' => 'w' } , 'GetIthacaCollegeLogicalCardId' => { 'user_card' => 'r', 'groups' => 'r', 'org_default_card_value' => 'r' } , 'get_user_card_userid' => { 'user_card' => 'r' } , 'get_user_card_group_id' => { 'user_card' => 'r' } , 'GetLogicalCardId' => { 'org_default_card_value' => 'r', 'user_card' => 'r' } , 'user_card_active_pass_count' => { 'user_pass' => 'r' } , 'pending_card' => { 'user_card' => 'r' } , 'delete_user_card_from_active_rider_table' => { 'active_rider_table' => 'w' } , 'get_active_rider_table' => { 'active_rider_table' => 'r' } , 'deactivate_user_card' => { 'audit_user_card' => 'w', 'user_card' => 'w' } , 'user_card_credential_exists' => { 'user_card' => 'r' } , 'insert_user_card' => { 'audit_user_card' => 'w', 'user_card' => 'w' } , 'validate_active_rider_table_logical_card_id' => { 'active_rider_table' => 'r' } , 'validate_rule' => { 'rule_mappings' => 'r', 'rule_class' => 'r' } , 'get_default_rule' => { 'rule_mappings' => 'r' } , 'get_rule_class' => { 'rule_class' => 'r' } , 'active_user_card_exists' => { 'org_default_card_value' => 'r', 'user_card' => 'r' } , 'insert_user_pass' => { 'audit_user_pass' => 'w', 'user_pass' => 'w' } , 'get_user_pass_logical_card_id' => { 'user_pass' => 'r' } , 'GetUserPass' => { 'user_card' => 'r', 'user_pass' => 'r', 'rule_class' => 'r' } , 'GetPassesOnCard' => { 'org_default_card_value' => 'r', 'user_card' => 'r', 'user_pass' => 'r', 'rule_class' => 'r', 'groups' => 'r' } , 'user_card_has_active_pass' => { 'user_pass' => 'r' } , 'activate_user_card_pass' => { 'user_pass' => 'w' } , 'user_card_pass_count' => { 'user_pass' => 'r' } , 'get_next_queue_order' => { 'user_pass' => 'r' } , 'deactivate_user_pass' => { 'audit_user_pass' => 'w', 'user_pass' => 'w', 'user_card' => 'r', 'rule_class' => 'r' } , 'update_user_pass' => { 'audit_user_pass' => 'w', 'user_pass' => 'w' } , 'get_pass_type_and_name' => { 'rule_class' => 'r', 'rule_mappings' => 'r' } , 'GetPricePoints' => { 'user_card' => 'r', 'groups' => 'r', 'org_default_card_value' => 'r', 'org_default_pass_value' => 'r', 'price_point' => 'r' } , 'check_dup_billing_log' => { 'billing_log' => 'r' } , 'insert_billing_log' => { 'billing_log' => 'w' } , 'diagnostic_log' => { 'diagnostic_log' => 'w' } , 'api_log' => { 'org_api_log' => 'w' } , 'admin_exists' => { 'admins' => 'r' } , 'get_admin_id' => { 'admins' => 'r' } , 'CreateAdmin' => { 'admins' => 'w', 'audit_admins' => 'w', 'groups' => 'r' } , 'GetAdmin' => { 'admins' => 'r', 'groups' => 'r' } , 'SetAdmin' => { 'admins' => 'w', 'audit_admins' => 'w', 'groups' => 'r' } , 'RemoveAdmin' => { 'admins' => 'w', 'audit_admins' => 'w' }, 'GetPendingQueue' => { 'org_card_order_queue' => 'r', user_card => 'r', 'org_default_card_value' => 'r', groups => 'r' }, 'GetPassOptions' => { 'pass_option' => 'r', 'admins' => 'r', 'groups' => 'r', 'rule_class' => 'r', 'rule_mappings' => 'r', 'org_default_pass_value' => 'r' }, 'SearchCards' => { 'user_card' => 'r', 'users' => 'r', 'groups' => 'r' }, 'SearchUsers' => { 'user_card' => 'r', 'users' => 'r', 'groups' => 'r' }, 'SearchAdmins' => { 'admins' => 'r', 'groups' => 'r' }, 'create_register_email' => { 'org_api_register_email' => 'w' }, 'get_register_email_info' => { 'org_api_register_email' => 'r' }, 'deactivate_register_email' => { 'org_api_register_email' => 'w' }, 'insert_password_reset' => { 'org_api_password_reset' => 'w' }, 'increment_user_reset_attempts' => { 'users' => 'w', 'audit_users' => 'w' } , 'get_password_reset_request_age' => { 'org_api_password_reset' => 'r' } , 'get_password_reset_request_user_id' => { 'org_api_password_reset' => 'r' } , 'deactivate_password_reset_for_user' => { 'org_api_password_reset' => 'w' } , 'get_user_group_name' => { 'users' => 'r', 'groups' => 'r' }, # inhereted 'get_user_card_group_name' => 'GetCard', 'get_dest_group_name' => 'get_user_card_group_name', 'get_dest_user_card_group_name' => 'GetCard', 'GetDestLogicalCardId' => 'GetLogicalCardId', 'confirm_card_user_id' => 'GetCard', # none 'valid_pass_param' => {} ); # # instead of having each function list the tables it needs, # maybe store them in the database and retrieve them as needed? # will consider for later. sub get_table_access_permissions_for_function { my $self = shift; my $func_name = shift; my $key; my $val; my $max_jump = scalar(keys(%function_locked_table_map)); $key = $func_name; return undef if !exists($function_locked_table_map{$key}); for (my $cur=0; $cur < $max_jump; $cur++) { $val = $function_locked_table_map{$key}; return $val if (ref($val) eq 'HASH'); $key = $val; } return undef; } sub begin_locked_transaction_for_function { my $self = shift; my $func_name = shift; my $h = $self->get_table_access_permissions_for_function($func_name); return undef if !$h; return undef if scalar(keys(%$h))==0; return $self->begin_locked_transaction( $h ) ; } sub begin_locked_transaction_for_functions { my $self = shift; # my $faref = shift; my %lhash; # foreach my $func (@$faref) foreach my $func (@_) { my $r = $self->get_table_access_permissions_for_function($func); #return undef if !$r; foreach my $k (keys(%$r)) { # upgrade read access to write # but not the other way around if ( !exists($lhash{$k}) ) { $lhash{$k} = $r->{$k}; } else { $lhash{$k} = 'w' if ($r->{$k} eq 'w'); } } } return $self->begin_locked_transaction(\%lhash); } ## same as above but allow for additional tables to be locked sub begin_locked_transaction_for_functions_and_tables { my $self = shift; my $func_aref = shift; my $table_href = shift; my %lhash; foreach my $func (@$func_aref) { my $r = $self->get_table_access_permissions_for_function($func); #return undef if !$r; foreach my $k (keys(%$r)) { # upgrade read access to write # but not the other way around if ( !exists($lhash{$k}) ) { $lhash{$k} = $r->{$k}; } else { $lhash{$k} = 'w' if ($r->{$k} eq 'w'); } } } foreach my $table (keys(%$table_href)) { $lhash{$table} = $table_href->{$table} } return $self->begin_locked_transaction(\%lhash); } ########## #sub lock_common { # my $self = shift; # ## my $lock_tables = ## $self->prepare("lock tables user_card write, " . ## " user_pass write, " . ## " active_rider_table write, " . ## " audit_user_pass write, " . ## " audit_user_card write, " . ## " org_card_order_queue write, " . ## " diagnostic_log write, " . ## " groups read, " . ## " users read, " . ## " rule_class read, " . ## " rule_mappings read, " . ## " org_default_card_value read, " . ## " org_default_pass_value read " ## ); ## $lock_tables->execute(); ## $self->lock_active(1); # ## $self->begin_locked_transaction_for_function("_common"); # #} sub begin_locked_transaction_common { my $self = shift; # $self->lock_common(); # $self->begin_work(); $self->begin_locked_transaction_for_function("_common"); } sub unlock { my $self = shift; my $unlock_tables = $self->prepare("unlock tables"); $unlock_tables->execute(); $self->lock_active(0); } sub begin_locked_transaction { my $self = shift; my $href = shift; my $n=0; my $query_str = "lock tables" ; while ( my ($k, $v) = each(%$href) ) { $query_str .= "," if ($n++)>0; $query_str .= " $k "; if ( $v =~ m/^[rR]/ ) { $query_str .= "read"; } elsif ($v =~ m/^[wW]/ ) { $query_str .= "write"; } } $self->lock_active(1); my $query = $self->prepare($query_str); $query->execute(); $self->begin_work(); return 1; } sub unlock_rollback { my $self = shift; $self->rollback(); my $query = $self->prepare("unlock tables"); $query->execute(); $self->lock_active(0); return 1; # return $self->rollback(); } sub unlock_commit { my $self = shift; my $query = $self->prepare("unlock tables"); $query->execute(); $self->lock_active(0); return $self->commit(); } #################################################### ## ## User Functions ## #################################################### my %users_field_map = ( userid => 'UserId', username => 'UserName', passwordhash => 'PasswordHash', first_name => 'FirstName', last_name => 'LastName', phone => 'Phone', email => 'Email', address => 'Address', city => 'City', state => 'State', zip => 'ZIP', comment => 'Comment', shipping_name => 'ShippingName', shipping_address => 'ShippingAddress', shipping_city => 'ShippingCity', shipping_state => 'ShippingState', shipping_zip => 'ShippingZIP', shipping_country_code => 'ShippingCountryCode', shipping_country_name => 'ShippingCountryName', reset_attempts => 'ResetAttempts', active => 'Active', group_id => 'GroupId' ); #################################################### sub get_user_id { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_user_id'; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $credential_match = " active = 1 "; my @credential_val; if ( defined($phash->{'UserName'}) ) { $credential_match .= " and username = ? "; push @credential_val , $phash->{'UserName'}; } if ( defined($phash->{'UserId'}) ) { $credential_match .= " and userid = ? "; push @credential_val, $phash->{'UserId'}; } if ( defined($phash->{'PasswordHash'}) ) { $credential_match .= " and passwordhash = ? "; push @credential_val, $phash->{'PasswordHash'}; } return undef if scalar(@credential_val)==0; ### if ( defined($phash->{'GroupId'}) ) { $credential_match .= " and group_id = ? "; push @credential_val, $phash->{'GroupId'}; } elsif ( defined($phash->{'GroupName'}) ) { $credential_match .= " and group_id = ? "; push @credential_val, $self->get_group_id( $phash->{'GroupName'} ); } ### $query = $self->prepare( "select userid " . " from users " . " where $credential_match " . " limit 1 "); $result = $query->execute(@credential_val); $row = $query->fetchrow_arrayref; # $rhash->{'UserId'} = $row->[0]; if (!$row) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return $row->[0]; } #################################################### sub CreateUser { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result); my $FUNC_NAME = "CreateUser"; my %blacklist_field = ( active => 1, created => 1, reset_attempts => 1, userid => 1 ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; if ( !defined($phash->{'UserName'}) || $self->username_exists($phash->{'UserName'}) ) { $rhash->{'Reason'} = "Invalid username"; $self->unlock_rollback() if $lock_local; return undef; } # default group or group name to group id conversion if ( !defined($phash->{GroupId}) ) { my $group_id = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ); if (!$group_id) { $rhash->{'Reason'} = "Invalid GroupName"; $self->unlock_rollback() if $lock_local; return undef; } $phash->{GroupId} = $group_id; # push @db_field, 'group_id'; # push @param, $group_id; } my @db_field; my @param; while (my ($k, $v) = each(%users_field_map) ) { next if ( $blacklist_field{lc($k)} ); push @db_field, $k; push @param, $phash->{$v}; } my $audit_id = $self->audit_users_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("insert into users " . " ( created, active, reset_attempts, " . join(", ", @db_field) . " ) values " . " ( now(), 1, 0 " . ", ?"x(scalar(@db_field)) . " )"); $result = $query->execute(@param); my $user_id = $self->last_insert_id(); $self->audit_users_end($user_id, $audit_id); $query = $self->prepare("select userid, " . join(', ', @db_field) . " from users where userid = ?"); $query->execute($user_id); my $href = $query->fetchrow_hashref; for (my $i=0; $i{$users_field_map{$db_field[$i]}} = $href->{$db_field[$i]}; } $rhash->{'UserId'} = $href->{'userid'}; $self->unlock_commit() if $lock_local; return 1; } #################################################### sub RemoveUser { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result); my $FUNC_NAME = "RemoveUser"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $user_id = $self->get_user_id($phash); if (!$user_id) { $rhash->{'Reason'} = "Invalid user credential"; $self->unlock_rollback() if $lock_local; return undef; } my %cards; my $r = $self->GetCards( \%cards, { UserId => $user_id } ); if (!$r) { $rhash->{'Reason'} = $cards{'Reason'}; $self->unlock_rollback() if $lock_local; return undef; } my $n_card = $cards{NCard}; for (my $k=0; $k < $n_card ; $k++) { my $ind = ""; $ind = "[$k]" if $k; $self->disassociate_user_from_card($cards{"CardId$ind"}); } my $audit_id = $self->audit_users_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("update users set active = 0 where userid = ? "); $result = $query->execute($user_id); $self->audit_users_end($user_id, $audit_id); $self->unlock_commit() if $lock_local; return 1; } #################################################### sub GetUser { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result); my $FUNC_NAME = "GetUser"; # my %blacklist_field = ( 'passwordhash' => 1 ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $userid = $self->get_user_id($phash); if (!$userid) { $rhash->{'Reason'} = "Invalid user credential"; $self->unlock_rollback() if $lock_local; return undef; } my $count=0; my $fields; while ( my ($k, $v) = each(%users_field_map) ) { # next if ( $blacklist_field{lc($k)} ); $fields .= ", " if ($count++); $fields .= " users.$k $v "; } $query = $self->prepare("select $fields , groups.group_name GroupName " . " from users , groups ". " where users.userid = ? " . " and users.active = 1 " . " and users.group_id = groups.group_id " . " limit 1"); $query->execute($userid); my $row = $query->fetchrow_hashref; if (!$row) { $rhash->{'Reason'} = "Invalid User"; $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; while ( my ($k, $v) = each(%$row) ) { $rhash->{$k} = $v; } return 1; } #################################################### sub SetUser { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result, $i, $j); my $FUNC_NAME= "SetUser"; my $update_fields; my @update_val; my %blacklist_field = ( username => 1, userid => 1 ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # could be updating password. only look up by username, userid and group my $userid = $self->get_user_id( { UserName => $phash->{UserName}, UserId => $phash->{UserId}, GroupId => $phash->{GroupId}, GroupName => $phash->{GroupName} } ); if (!defined($userid)) { $rhash->{'Reason'} = "Invalid user credential"; $self->unlock_rollback() if $lock_local; return undef; } while ( my ($k, $v) = each(%users_field_map) ) { next if $blacklist_field{lc($k)} || !exists($phash->{$v}); $update_fields .= ", " if $update_fields; $update_fields .= " $k = ? "; push @update_val, $phash->{$v}; } # special consideration for groups if ( !defined($phash->{GroupId}) ) { if ( defined($phash->{GroupName}) ) { my $group_id = $self->get_group_id( $phash->{GroupName} ); if ( !$group_id ) { $rhash->{'Reason'} = "Invalid GroupName"; $self->unlock_rollback() if $lock_local; return undef; } $update_fields .= ", " if $update_fields; $update_fields .= " group_id = ? "; push @update_val, $group_id; } } if (scalar(@update_val)==0) { $rhash->{'Reason'} = "Nothing to update"; $self->unlock_rollback() if $lock_local; return undef; } push @update_val, $userid; my $audit_id = $self->audit_users_start($userid, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("update users " . " set $update_fields " . " where userid = ?"); $result = $query->execute(@update_val); $self->audit_users_end($userid, $audit_id ); $rhash->{'UserId'} = $userid; $self->unlock_commit() if $lock_local; return 1; } #################################################### sub username_exists { my $self = shift; my $username = shift; my $FUNC_NAME = 'username_exists'; my ($query, $result, $row); my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( { 'users' => 'r' } ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select count(userid) num " . " from users " . " where username = ? " . " and active = 1 "); $result = $query->execute($username); $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return ($row->[0] != 0); } #################################################### sub valid_user { my $self = shift; my $userid = shift; my $FUNC_NAME = 'valid_user'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'users' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select count(userid) num " . " from users " . " where userid = ? " . " and username is not null " . " and passwordhash is not null"); my $result = $query->execute($userid); $self->unlock_commit() if $lock_local; return ($query->fetchrow_arrayref->[0] == 1); } #################################################### ## ## Card Functions ## #################################################### my @user_card_field = qw( issued mag_token rfid_token comment userid active deactivated lastused firstused group_id issuetype ); my %user_card_field_map = ( mag_token => 'MagToken', rfid_token => 'RFIDToken', logical_card_id => 'CardId', active => 'Active', comment => 'Comment', lastused => 'LastUsed', issued => 'Issued', firstused => 'FirstUsed', userid => 'UserId', deactivated => 'Deactivated', group_id => 'GroupId', issuetype => 'IssueType' ); ########### sub get_default_mag_track { my $self = shift; my $group_id = shift; my $FUNC_NAME = 'get_default_mag_track'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'org_default_card_value' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select mag_track " . " from org_default_card_value " . " where group_id = ? " . " or group_id is null " . " order by group_id desc " . " limit 1"); $query->execute($group_id); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0]; } ########### sub get_default_rflength { my $self = shift; my $group_id = shift; my $FUNC_NAME = 'get_default_rflength'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'org_default_card_value' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select rf_length " . " from org_default_card_value " . " where group_id = ? " . " or group_id is null " . " order by group_id desc " . " limit 1"); $query->execute($group_id); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0]; } ########### sub get_default_rfsite { my $self = shift; my $group_id = shift; my $FUNC_NAME = 'get_default_rfsite'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select rf_site " . " from org_default_card_value " . " where group_id = ? " . " or group_id is null " . " order by group_id desc " . " limit 1"); $query->execute($group_id); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0]; } ### sub construct_mag_token { my $self = shift; my $phash = shift; my $FUNC_NAME = 'construct_mag_token'; return $phash->{'MagToken'} if $phash->{'MagToken'}; return undef if !$phash->{'MagStripe'}; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $mag_track = ( $phash->{'MagTrack'} || $self->get_default_mag_track( $phash->{'GroupId'} ) ); $self->unlock_commit() if $lock_local; return $mag_track . ":" . $phash->{'MagStripe'}; } ### sub construct_rfid_token { my $self = shift; my $phash = shift; my $FUNC_NAME = 'construct_rfid_token'; return $phash->{'RFIDToken'} if $phash->{'RFIDToken'}; return undef if !$phash->{'RFID'}; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $rflength = ( $phash->{'RFLength'} || $self->get_default_rflength( $phash->{'GroupId'} ) ); my $rfsite = ( $phash->{'RFSite'} || $self->get_default_rfsite( $phash->{'GroupId'} ) ); $self->unlock_commit() if $lock_local; return $rflength. ":" . $rfsite . ":" . $phash->{'RFID'}; } ########### sub construct_user_card_credential_match { my $self = shift; my $phash = shift; my $FUNC_NAME = 'construct_user_card_credential_match'; my $credential_match = "true"; my @credential_val; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; if (defined($phash->{'MagToken'}) || defined($phash->{'MagStripe'}) ) { $credential_match .= " and mag_token = ? "; push @credential_val, $self->construct_mag_token($phash); } if (defined($phash->{'RFIDToken'}) || defined($phash->{'RFID'}) ) { $credential_match .= " and rfid_token = ? "; push @credential_val, $self->construct_rfid_token($phash); } if (defined($phash->{'CardId'})) { $credential_match .= " and logical_card_id = ? "; push @credential_val, $phash->{'CardId'}; } return ($credential_match, \@credential_val) if (scalar(@credential_val)==0); ### if (defined($phash->{'GroupId'})) { $credential_match .= " and group_id = ? "; push @credential_val, $phash->{'GroupId'}; } elsif (defined($phash->{'GroupName'})) { $credential_match .= " and group_id = ? "; push @credential_val, $self->get_group_id( $phash->{'GroupName'} ); } ### $self->unlock_commit() if $lock_local; return ($credential_match, \@credential_val); } ### sub update_user_card { my $self = shift; my $logical_card_id = shift; my $param_hash = shift; my $FUNC_NAME = "update_user_card"; return undef if !$logical_card_id; my $str; my @val; while ( my ($k, $v) = each(%$param_hash) ) { next if (!$user_card_field_map{$k}); $str .= " , " if $str; $str .= " $k = ? "; push @val, $v; } return undef if (scalar(@val)==0); my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'audit_user_card' => 'w', # 'user_card' => 'w' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $audit_id = $self->audit_user_card_start($logical_card_id, "$PACKAGE_NAME: $FUNC_NAME"); my $query = $self->prepare("update user_card set $str where logical_card_id = ? "); $query->execute(@val, $logical_card_id); $self->audit_user_card_end($logical_card_id, $audit_id); $self->unlock_commit() if $lock_local; return 1; } ########### sub GetCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetCard'; my ($query, $result); my @field; my @db_field; my %blacklisted_field = ( acitve => '1' ); my %thash = %$phash; while ( my ($k, $v) = each(%user_card_field_map) ) { next if (defined($blacklisted_field{$k})); push @field, $v; push @db_field, "$k $v"; } my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # $phash->{GroupId} = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ) # if (!$phash->{GroupId}); # my $logical_card_id = # $self->GetLogicalCardId($phash); my $logical_card_id; if ($thash{CardId}) { $logical_card_id = $self->GetLogicalCardId( { CardId => $thash{CardId} } ) } else { $thash{GroupId} = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ) if (!$phash->{GroupId}); $logical_card_id = $self->GetLogicalCardId(\%thash); } if (!$logical_card_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid Card"; return undef; } $query = $self->prepare("select user_card." . join(", user_card.", @db_field) . " , groups.group_name GroupName " . " from user_card, groups " . " where user_card.logical_card_id = ? " . " and user_card.active = 1 " . " and user_card.group_id = groups.group_id " . " order by user_card.logical_card_id " . " limit 1"); $result = $query->execute($logical_card_id); my $row = $query->fetchrow_hashref; if (!$row) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid Credential"; return undef; } ($rhash->{'MagTrack'}, $rhash->{'MagStripe'}) = split(/:/, $row->{'MagToken'}); ($rhash->{'RFLength'}, $rhash->{'RFSite'}, $rhash->{'RFID'}) = split(/:/, $row->{'RFIDToken'}); for (my $i=0; $i{$field[$i]} = $row->{$field[$i]}; } $rhash->{GroupName} = $row->{GroupName}; $self->unlock_commit() if $lock_local; return 1; } #################################################### #sub get_cards { sub GetCards { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetCards'; my ($query, $result); my @field; my @db_field; my %blacklisted_field = ( active => '1' ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # my $user_id = $self->get_user_id($phash); my $user_id = $self->get_user_id( { UserName => $phash->{UserName}, UserId => $phash->{UserId}, GroupId => $phash->{UserGroupId}, GroupName => $phash->{UserGroupName} } ); my $max_card = $phash->{'MaxCard'}; if (!defined($user_id)) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid UserId"; return undef; } while ( my ($k, $v) = each(%user_card_field_map) ) { next if (defined($blacklisted_field{$k})); push @field, $v; push @db_field, "$k $v"; } my @param; push @param, $user_id; my $limit; if ($max_card) { $limit = " limit ? "; push @param, $max_card; } $query = $self->prepare("select " . join(", ", @db_field) . " " . " from user_card " . " where userid = ? " . " and active = 1 " . " order by CardId " . " $limit "); $result = $query->execute(@param); my $k=0; my $ind = ''; while (my $row = $query->fetchrow_hashref) { last if $max_card && ($k>=$max_card); ($rhash->{"MagTrack" . $ind }, $rhash->{"MagStripe" . $ind }) = split(/:/, $row->{'MagToken'}); ($rhash->{"RFLength" . $ind }, $rhash->{"RFSite" . $ind }, $rhash->{"RFID" . $ind }) = split(/:/, $row->{'RFIDToken'}); for (my $i=0; $i{ $field[$i] . $ind } = $row->{$field[$i]}; } $ind = "[" . (++$k) . "]"; } $rhash->{'NCard'} = $k; $self->unlock_commit() if $lock_local; return 1; } #################################################### ### DEFAULT TO ORG ### this might need to change depending on how the ### system evolves #sub get_default_card_group_info { sub GetDefaultCardGroupInfo { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetDefaultCardGroupInfo'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select group_id GroupId, group_name GroupName from groups where group_name = ? "); $query->execute($DEFAULT_GROUP_NAME); my $row = $query->fetchrow_hashref; while ( my ($k, $v) = each(%$row) ) { $rhash->{$k} = $v; } $self->unlock_commit() if $lock_local; return 1; } ### sub get_group_name { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_group_name'; return $phash->{GroupName} if ($phash->{GroupName}); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select group_name from groups where group_id = ?"); $query->execute($phash->{GroupId}); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return $DEFAULT_GROUP_NAME if !$row; return $row->[0]; } ### sub get_user_card_group_name { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_user_card_group_name'; my %r; $self->GetCard(\%r, $phash); return $r{GroupName}; } ### sub get_dest_group_name { my $self = shift; my $phash = shift; my %thash; $thash{GroupId} = $phash->{DestGroupId} if $phash->{DestGroupId}; $thash{GroupName} = $phash->{DestGroupName} if $phash->{DestGroupName}; #return $self->get_user_card_group_name(\%thash); return $self->get_group_name(\%thash); } sub get_dest_user_card_group_name { my $self = shift; my $phash = shift; my $to_logical_card_id = $self->GetDestLogicalCardId($phash); my %r; $self->GetCard(\%r, { CardId => $to_logical_card_id } ); return $r{GroupName}; } ### sub get_user_pass_group_name { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_user_pass_group_name'; return undef if (!$phash->{PassId}); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select groups.group_name from groups, user_card, user_pass where user_pass.user_pass_id = ? and user_card.logical_card_id = user_pass.logical_card_id and groups.group_id = user_card.group_id"); $query->execute($phash->{PassId}); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; } ### sub get_user_group_name { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_user_group_name'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $user_id = $self->get_user_id($phash); my $query = $self->prepare("select groups.group_name from users, groups where users.userid = ? and users.group_id = groups.group_id "); $query->execute($user_id); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; #return $DEFAULT_GROUP_NAME; } ### sub get_admin_group_name { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_admin_group_name'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $str = " admins.active = 1 "; my @val; if ($phash->{UserId}) { $str .= " and admins.userid = ? "; push @val, $phash->{UserId}; } if ($phash->{UserName}) { $str .= " and admins.username = ? "; push @val, $phash->{UserName}; } my $query = $self->prepare("select groups.group_name from groups, admins where $str and groups.group_id = admins.group_id"); $query->execute(@val); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return $row->[0]; } ### sub get_group_id { my $self = shift; my $group_name = shift; my $FUNC_NAME = 'get_group_id'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( { 'groups' => 'r' } ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select group_id from groups where group_name = ? "); $query->execute($group_name); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; } ### my %table_id_field = ( user_card => 'logical_card_id', ); ### sub get_entry_group_name { my $self = shift; my $table = shift; my $id = shift; my $FUNC_NAME = 'get_entry_group_name'; return undef if (!$table_id_field{$table}); my $lock_local = ( $self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'groups' => 'r', $table => 'r' } ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select groups.group_name " . " from $table, groups " . " where $table." . $table_id_field{$table} . " = ?" . " and groups.group_id = $table.group_id"); $query->execute($id); my $row = $query->fetchrow_arrayref; $$self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; } ############ #sub issue_blank_card { sub IssueBlankCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "IssueBlankCard"; my ($query, $result); my %blacklisted_field = ( active => 1, mag_token => 1, rfid_token => 1, issued => 1, group_id => 1 ); my @val; my @db_field; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # my $user_id = $self->get_user_id($phash); my $user_id = $self->get_user_id( { UserName => $phash->{UserName}, UserId => $phash->{UserId}, GroupId => $phash->{UserGroupId}, GroupName => $phash->{UserGroupName} } ); if (!defined($user_id)) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid UserId"; return undef; } $phash->{UserId} = $user_id; while ( my ($k, $v) = each(%user_card_field_map) ) { next if defined($blacklisted_field{$k}); push @db_field, $k; push @val, $phash->{$v}; } my %group_hash; $self->GetDefaultCardGroupInfo(\%group_hash, $phash); my $group_id = $group_hash{'GroupId'}; my $audit_id = $self->audit_user_card_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("insert into user_card ( issued, active, group_id, " . join(", ", @db_field) . " ) " . "values ( now(), 1, ? " . ", ?"x(scalar(@db_field)) . " ) "); $result = $query->execute($group_id, @val); $rhash->{'CardId'} = $self->last_insert_id(); $self->audit_user_card_end($rhash->{'CardId'}, $audit_id ); $query = $self->prepare("insert into org_card_order_queue (userid, logical_card_id, created, processed, comment, pending) " . "values (?, ?, now(), null, null, 1)"); $result = $query->execute($user_id, $rhash->{'CardId'}); $self->unlock_commit() if $lock_local; # DO NOT put newly issued card into active_rider_table, will be handled whent he entry is removed from ordered queue return 1; } sub disassociate_user_from_card { my $self = shift; my $card_id = shift; my $FUNC_NAME = "disassociate_user_from_card"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'audit_user_card' => 'w', # 'user_card' => 'w' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $audit_id = $self->audit_user_card_start($card_id, "$PACKAGE_NAME: $FUNC_NAME"); my $query = $self->prepare("update user_card " . " set userid = null " . " where logical_card_id = ?"); my $result = $query->execute($card_id); $self->audit_user_card_end($card_id); $self->unlock_commit() if $lock_local; return 1; } sub associate_user_to_card { my $self = shift; my $card_id = shift; my $user_id = shift; my $FUNC_NAME = "associate_user_to_card"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'audit_user_card' => 'w', # 'user_card' => 'w' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $audit_id = $self->audit_user_card_start($card_id, "$PACKAGE_NAME: $FUNC_NAME"); my $query = $self->prepare("update user_card " . " set userid = ? " . " where logical_card_id = ?"); my $result = $query->execute($user_id, $card_id); $self->audit_user_card_end($card_id, $audit_id ); $self->unlock_commit() if $lock_local; return 1; } #sub get_ithacacollege_logical_card_id { sub GetIthacaCollegeLogicalCardId { my $self = shift; my $phash = shift; my $FUNC_NAME = 'GetIthacaCollegeLogicalCardId'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( # { # 'user_card' => 'r', # 'groups' => 'r', # 'org_default_card_value' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $mag_token = $self->construct_mag_token( $phash ); if (!$mag_token) { $self->unlock_rollback() if $lock_local; return undef; } my $query = $self->prepare("select user_card.logical_card_id " . " from user_card, groups " . " where user_card.mag_token like concat(?, '__') " . " and groups.group_name = 'ITHACACOLLEGE' " . " and groups.group_id = user_card.group_id " . " and user_card.active = 1 "); $query->execute($mag_token); my $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return undef ; } $self->unlock_commit() if $lock_local; return $row->[0]; } ######################### ## ## ## Search Functions ## ## sub SearchCards { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "SearchCards"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my %group_hash; if ($phash->{NGroup}) { my $n_group = $phash->{NGroup}; for (my $k=0; $k<$n_group; $k++) { my $ind = ""; $ind = "[$k]" if $k; $group_hash{ $phash->{"GroupName$ind"} } = 1; } } my @param; for (my $i=0; $i<8; $i++) { push @param, '%' . $phash->{SearchText} . '%' ; } my $has_limit = 0; if ($phash->{MaxItem}) { $has_limit = 1; push @param, $phash->{MaxItem}; } my $query = $self->prepare("select user_card.logical_card_id CardId, " . " user_card.mag_token MagToken, " . " user_card.rfid_token RFIDToken, " . " user_card.comment Comment, " . " user_card.userid UserId, " . " user_card.lastused LastUsed, " . " user_card.firstused FirstUsed, " . " user_card.group_id GroupId, " . " users.username UserName, " . " groups.group_name GroupName " . " from user_card " . " left join users on (users.userid = user_card.userid and users.active = 1) " . " left join groups on (groups.group_id = user_card.group_id) " . " where user_card.active = 1 " . " and ( user_card.mag_token like ? " . " or user_card.rfid_token like ? " . " or user_card.comment like ? " . " or user_card.issued like ? " . " or user_card.lastused like ? " . " or user_card.firstused like ? " . " or users.username like ? " . " or groups.group_name like ? ) " . ( $has_limit ? " limit ? " : "" ) ); $query->execute(@param); my $count=0; while (my $row = $query->fetchrow_hashref) { next if ( !$group_hash{ $row->{GroupName} }); my $ind = ( $count ? "[$count]" : "" ); foreach my $k (keys(%$row)) { $rhash->{"$k$ind"} = $row->{$k}; } $count++; } $rhash->{NItem} = $count; $self->unlock_commit() if $lock_local; return 1; } ## sub SearchUsers { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "SearchUsers"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my %group_hash; if ($phash->{NGroup}) { my $n_group = $phash->{NGroup}; for (my $k=0; $k<$n_group; $k++) { my $ind = ""; $ind = "[$k]" if $k; $group_hash{ $phash->{"GroupName$ind"} } = 1; } } my @param; my $has_limit = 0; if ($phash->{MaxItem}) { $has_limit = 1; } my %blacklist_field = ( active => 1, reset_attempts => 1, passwordhash => 1 ); my $search_fields = "false"; my $returned_fields; while ( my ($k, $v) = each(%users_field_map) ) { next if $blacklist_field{lc($k)}; $search_fields .= " or "; $search_fields .= " users.$k like ? "; push @param, '%' . $phash->{SearchText} . '%'; $returned_fields .= ", " if $returned_fields; $returned_fields .= " users.$k $v "; } if ($has_limit) { push @param, $phash->{MaxItem}; } my $query = $self->prepare("select $returned_fields , groups.group_name GroupName " . " from users, groups " . " where users.active = 1 " . " and users.group_id = groups.group_id " . " and ( $search_fields ) " . ( $has_limit ? " limit ? " : "" ) ); $query->execute(@param); my $count=0; while (my $row = $query->fetchrow_hashref) { next if (!$group_hash{ $row->{GroupName} }); my $ind = ( $count ? "[$count]" : "" ); foreach my $k (keys(%$row)) { $rhash->{"$k$ind"} = $row->{$k}; } $count++; } $rhash->{NItem} = $count; $self->unlock_commit() if $lock_local; return 1; } ## my %admins_field_map = ( username => 'UserName', password => 'PasswordHash', userid => 'UserId', group_id => 'GroupId' ); sub SearchAdmins { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "SearchAdmins"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my %blacklist_field = ( 'password' => 1 ); my @param; my %group_hash; if ($phash->{NGroup}) { my $n_group = $phash->{NGroup}; for (my $k=0; $k<$n_group; $k++) { my $ind = ""; $ind = "[$k]" if $k; $group_hash{ $phash->{"GroupName$ind"} } = 1; } } my $has_limit = 0; if ($phash->{MaxItem}) { $has_limit = 1; } my $search_fields = "false"; my $returned_fields; while ( my ($k, $v) = each(%admins_field_map) ) { next if $blacklist_field{lc($k)}; $search_fields .= " or "; $search_fields .= " admins.$k like ? "; push @param, '%' . $phash->{SearchText} . '%'; $returned_fields .= ", " if $returned_fields; $returned_fields .= " admins.$k $v "; } if ($has_limit) { push @param, $phash->{MaxItem}; } my $query = $self->prepare("select $returned_fields , groups.group_name GroupName " . " from admins left join groups on (admins.group_id = groups.group_id) " . " where admins.active = 1 " . " and ( $search_fields ) " . ( $has_limit ? " limit ? " : "" ) ); $query->execute(@param); my $count=0; while (my $row = $query->fetchrow_hashref) { next if (!$group_hash{ $row->{GroupName} }); my $ind = ( $count ? "[$count]" : "" ); foreach my $k (keys(%$row)) { $rhash->{"$k$ind"} = $row->{$k}; } $count++; } $rhash->{NItem} = $count; $self->unlock_commit() if $lock_local; return 1; } #################################################### # # Associates a pre-existing card in the database to # a user. # #sub add_card { sub AddCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "AddCard"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # my $user_id = $self->get_user_id($phash); my $user_id = $self->get_user_id( { UserName => $phash->{UserName}, UserId => $phash->{UserId} # GroupId => $phash->{UserGroupId}, # GroupName => $phash->{UserGroupName} } ); if (!$user_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid User"; return undef; } # we have to do special processing if it's an ithacacollege card my $logical_card_id = ( (lc($phash->{'Type'}) eq 'ithacacollege') ? $self->GetIthacaCollegeLogicalCardId( $phash ) : $self->GetLogicalCardId( $phash ) ); if (!$logical_card_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid Card (1)"; return undef; } my $card_orig_userid = $self->get_user_card_userid( $logical_card_id ); # Card could be associated to 'ghost' user: A user # without a username or password hash. In this # case, assigning the card is allowed. if ($card_orig_userid) { if ( $self->valid_user($card_orig_userid) ) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid Card (2)"; return undef; } $self->disassociate_user_from_card($logical_card_id); } # set user_card entry to userid $self->associate_user_to_card($logical_card_id, $user_id); $self->unlock_commit() if $lock_local; $rhash->{'CardId'} = $logical_card_id; return 1; } #sub transfer_card { sub TransferCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'TransferCard'; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction_common() if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $phash->{GroupId} = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ) if (!$phash->{GroupId}); $phash->{ToGroupId} = $self->get_group_id( $phash->{ToGroupName} || $DEFAULT_GROUP_NAME ) if (!$phash->{ToGroupId}); my ($i, $j, $k, $n, $ind); my %thash; my $from_logical_card_id = $self->GetLogicalCardId($phash); my $to_logical_card_id = $self->GetDestLogicalCardId($phash); if (!$from_logical_card_id || !$to_logical_card_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid source or destination card (from $from_logical_card_id, to $to_logical_card_id)"; return undef; } my $user_id = $self->get_user_card_userid($from_logical_card_id); # my $to_card_user_id = # $self->get_user_card_userid($to_logical_card_id); # # if ($to_card_user_id != $user_id) # { # $self->unlock_rollback(); # $rhash->{'Reason'} = "Permission Denied: Destination card not owned by user"; # return undef; # } $self->GetPassesOnCard( \%thash, { CardId => $from_logical_card_id } ); $n = $thash{'NPass'}; for ($i=0; $i<$n; $i++) { $ind = "[$i]" if $i>0; my %dummy; # $self->transfer_pass( \%dummy, { ToCardId => $to_logical_card_id, $self->TransferPass( \%dummy, { ToCardId => $to_logical_card_id, PassId => $thash{'PassId' . $ind } }, 0 ); } $self->disassociate_user_from_card($from_logical_card_id); $self->associate_user_to_card($to_logical_card_id, $user_id); $self->unlock_commit() if $lock_local; $rhash->{'CardId'} = $to_logical_card_id; return 1; } #################################################### sub get_user_card_userid { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'get_user_card_userid'; return undef if !$logical_card_id; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( # { # 'user_card' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select userid " . " from user_card " . " where logical_card_id = ? "); $query->execute($logical_card_id); my $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return $row->[0]; } ### sub get_user_card_group_id { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'get_user_card_group_id'; return undef if !$logical_card_id; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( # { # 'user_card' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select group_id " . " from user_card " . " where logical_card_id = ? "); $query->execute($logical_card_id); my $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return $row->[0]; } ### #sub get_logical_card_id sub GetLogicalCardId { my $self = shift; my $phash = shift; my $FUNC_NAME = 'GetLogicalCardId'; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my ($credential_match, $credential_param_ref) = $self->construct_user_card_credential_match($phash); if (scalar(@$credential_param_ref)==0) { $self->unlock_rollback() if $lock_local; return undef; } my $query = $self->prepare("select logical_card_id " . " from user_card " . " where $credential_match " . " and active = 1 " . " limit 1 "); $query->execute(@$credential_param_ref); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; } #sub get_dest_logical_card_id { sub GetDestLogicalCardId { my $self = shift; my $phash = shift; # return $self->get_logical_card_id( { #UserId => $phash->{'UserId'}, my $FUNC_NAME = 'GetDestLogicalCardId'; return $self->GetLogicalCardId( { MagToken=> $phash->{'ToMagToken'}, MagTrack => $phash->{'ToMagTrack'}, MagStripe => $phash->{'ToMagStripe'}, RFLength => $phash->{'ToRFLength'}, RFID => $phash->{'ToRFID'}, RFIDToken => $phash->{'ToRFIDToken'}, CardId => $phash->{'ToCardId'}, GroupId => $phash->{'ToGroupId'} } ); } #### sub user_card_active_pass_count { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'user_card_active_pass_count'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( # { # 'user_pass' => 'r' # } # ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select count(user_pass_id) ". " from user_pass " . " where logical_card_id = ? " . " and expired = 0 " . " and active = 1 "); $query->execute($logical_card_id); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0]; } ##### sub pending_card { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'pending_card'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_card' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select mag_token, rfid_token " . " from user_card " . " where logical_card_id = ? " . " and active = 1 " ); $query->execute($logical_card_id); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return 0 if !$row; return !($row->[0]) && !($row->[1]); } ##### sub delete_user_card_from_active_rider_table { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'delete_user_card_from_active_rider_table'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'active_rider_table' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; if (!$self->validate_active_rider_table_logical_card_id( $logical_card_id )) { $self->unlock_rollback() if $lock_local; return undef } my $query = $self->prepare(" insert into " . " active_rider_table (logical_card_id, deleted) " . " values ( ?, 1) "); $query->execute($logical_card_id); $self->unlock_commit() if $lock_local; return 1; } ##### sub confirm_card_user_id { my $self = shift; my $phash = shift; my $user_id = shift; my $FUNC_NAME = 'confirm_card_user_id'; my %thash; my $r = $self->GetCard(\%thash, $phash); return 0 if (!$r) or ($thash{UserId} != $user_id); return 1; } ##### my %active_rider_table_map = ( logical_card_id => 'logical_card_id', seq_num => 'seq_num', rfid_token => 'rfid_token', mag_token => 'mag_token', rule_name => 'rule_name', rule_param => 'rule_param', deleted => 'deleted' ); sub get_active_rider_table #sub GetActiveRiderTable { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'get_active_rider_table'; my $logical_card_id = $phash->{'logical_card_id'}; return undef if !$logical_card_id; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'active_rider_table' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select max(seq_num) m " . " from active_rider_table " . " where deleted = 0 " . " and logical_card_id = ? "); $query->execute($logical_card_id); my $seq_num = $query->fetchrow_arrayref->[0]; if (!$seq_num) { $self->unlock_commit() if $lock_local; return undef; } $query = $self->prepare("select " . join(", ", keys(%active_rider_table_map)) . " from active_rider_table " . " where logical_card_id = ? " . " and deleted = 0 " . " and seq_num = ?"); $query->execute($logical_card_id, $seq_num); my $row = $query->fetchrow_hashref; $self->unlock_commit() if $lock_local; return undef if (!$row); foreach my $k (keys(%active_rider_table_map)) { $rhash->{$active_rider_table_map{$k}} = $row->{$k}; } return 1; } ##### sub deactivate_user_card { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = "deactivate_user_card"; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'audit_user_card' => 'w', 'user_card' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $audit_id = $self->audit_user_card_start($logical_card_id, "$PACKAGE_NAME: $FUNC_NAME"); my $query = $self->prepare("update user_card " . " set active = 0, " . " deactivated = now() " . " where logical_card_id = ?"); my $result = $query->execute($logical_card_id); $self->audit_user_card_end($logical_card_id, $audit_id); $self->unlock_commit() if $lock_local; } ### # deactivate user_card entry ### #sub remove_card { sub RemoveCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "RemoveCard"; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # $phash->{GroupId} = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ) # if (!$phash->{GroupId}); if ($phash->{GroupName} && !$phash->{GroupId}) { $phash->{GroupId} = $self->get_group_id( $phash->{GroupName} ); } my $logical_card_id = $self->GetLogicalCardId($phash); if (!$logical_card_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid CardId"; return undef; } # if card isn't an 'ordered' card if ( !$self->pending_card($logical_card_id) ) { if (!$self->delete_user_card_from_active_rider_table($logical_card_id)) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Internal Error"; return undef; } } else # if it is, remove it from the card order queue { my %thash; if (!$self->RemovePendingQueueByCardId( \%thash, { 'CardId' => $logical_card_id } )) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = $thash{'Reason'}; return undef; } } $self->deactivate_user_card($logical_card_id); $self->unlock_commit() if $lock_local; return 1; } ### sub GetPendingQueue { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "GetPendingQueue"; my ($query, $result, $row); $query = $self->prepare("select org_card_order_queue_id, userid, logical_card_id, created, processed, comment, pending from org_card_order_queue where pending = 1 order by org_card_order_queue_id"); $query->execute(); my $ind; my $n=0; while (my $row = $query->fetchrow_hashref) { $ind = "[$n]" if $n>0; $n++; $rhash->{'QueueId' . $ind} = $row->{org_card_order_queue_id}; $rhash->{'UserId' . $ind} = $row->{userid}; $rhash->{'CardId' . $ind} = $row->{logical_card_id}; $rhash->{'Created' . $ind} = $row->{created}; my %trhash; my %tphash = ( CardId => $row->{logical_card_id} ); my $r = $self->GetCard(\%trhash, \%tphash); $rhash->{'IssueType' . $ind} = $trhash{'IssueType'}; } $rhash->{NCard} = $n; return 1; } ### sub GetPendingQueueCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "GetPendingQueueCard"; my $lock_local = ($self->lock_active() ? 0 : 1); my $queue_id = $phash->{QueueId}; if (!$queue_id) { $rhash->{Reason} = "Invalid QueueId"; return undef ; } # $self->begin_locked_transaction_common() if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select logical_card_id from org_card_order_queue where org_card_order_queue_id = ? and pending = 1"); $query->execute($queue_id); my $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = "No cards found"; return undef; } my $logical_card_id = $row->[0]; return $self->GetCard($rhash, { CardId => $logical_card_id } ); } ### sub ProcessPendingQueue { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "ProcessPendingQueue"; my ($query, $row); my $lock_local = ($self->lock_active() ? 0 : 1); my $queue_id = $phash->{QueueId}; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select logical_card_id, userid from org_card_order_queue where org_card_order_queue_id = ? and pending = 1"); $query->execute($queue_id); $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = "No Pending Card"; return undef; } $phash->{UserId} = $row->[1]; $phash->{CardId} = $row->[0]; my %resp; my $r = $self->TransferCard(\%resp, $phash); if (!$r) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = $resp{Reason}; return undef; } my $card_id = $resp{CardId}; $rhash->{CardId} = $resp{CardId}; %resp = (); $r = $self->RemoveCard(\%resp, { CardId => $phash->{CardId} } ); if (!$r) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = $resp{Reason}; return undef; } $query = $self->prepare("update org_card_order_queue set pending = 0 where org_card_order_queue_id = ?"); $query->execute($queue_id); $self->unlock_commit() if $lock_local; return 1; } ### sub RemovePendingQueue { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "RemovePendingQueue"; my ($query, $row, $queue_id); $queue_id = $phash->{QueueId}; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select logical_card_id from org_card_order_queue where org_card_order_queue_id = ? and pending = 1"); $query->execute($queue_id); $row = $query->fetchrow_arrayref; $queue_id = $phash->{QueueId}; if (!$queue_id || !$row) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = "No entry in card order queue"; return undef; } my %t; $self->RemoveCard(\%t, { CardId => $row->[0] } ); $query = $self->prepare("update org_card_order_queue set pending = 0 where org_card_order_queue_id = ?"); $query->execute($queue_id); $self->unlock_commit() if $lock_local; return (1, "RemovePendingQueue"); } #### # # remove only the org_card_order_queue entry by the card id # sub RemovePendingQueueByCardId { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "RemovePendingQueueByCardId"; my ($query, $row, $card_id, $queue_id); $card_id = $phash->{CardId}; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select org_card_order_queue_id, logical_card_id from org_card_order_queue where pending = 1 and logical_card_id = ?"); $query->execute($card_id); $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = "No entry in card order queue"; return undef; } $queue_id = $row->[0]; $query = $self->prepare("update org_card_order_queue set pending = 0 where org_card_order_queue_id = ?"); $query->execute( $queue_id ); $self->unlock_commit() if $lock_local; return (1, "RemovePendigQueueByCardId"); } ############################ #sub active_user_card sub user_card_credential_exists { my $self = shift; my $param_hash = shift; my $FUNC_NAME = 'user_card_credential_exists'; my @field = qw( logical_card_id mag_token rfid_token ); my $query; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_card' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; foreach my $field (@field) { if ($param_hash->{$field}) { $query = $self->prepare("select count(logical_card_id) num " . " from user_card " . " where " . $field . " = ? " . " and active = 1 " . " limit 1 "); $query->execute($param_hash->{$field}); # return 1 if $query->fetchrow_arrayref->[0] > 0; if ($query->fetchrow_arrayref->[0] > 0) { $self->unlock_commit() if $lock_local; return 1; } } } $self->unlock_commit() if $lock_local; return 0; } ############################ # # insert user card helper function # active defaults to 1 # issued defaults to now() # sub insert_user_card { my $self = shift; my $param_hash = shift; my $FUNC_NAME = "insert_user_card"; my @field; my @val; my $query; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'audit_user_card' => 'w', 'user_card' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; if ( $self->user_card_credential_exists( $param_hash ) ) { $self->unlock_rollback() if $lock_local; return undef } my @default_field = ('issued', 'active'); my @default_value = ('now()', '1'); my @default_token; # construct default values for (my $i=0; $i{$f})) { push @default_token, "?"; push @val, $param_hash->{$f}; } else { push @default_token, $default_value[$i]; } } # populate values foreach my $k (keys(%user_card_field_map)) { next if grep $_ eq $k, @default_field; push @field, $k; push @val, (defined($param_hash->{$k}) ? $param_hash->{$k} : undef ); } my $audit_id = $self->audit_user_card_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("insert into user_card ( " . join(', ', @field) . ") " . "values ( " . join(', ', @default_token) . ", ?"x(scalar(@field)-scalar(@default_token)) . ")"); $query->execute(@val); my $logical_card_id = $self->last_insert_id(); $self->audit_user_card_end($logical_card_id, $audit_id); $self->unlock_commit() if $lock_local; return $logical_card_id } ############################ ########## ### # # returns 0 if logical_card_id is not found or last entry is deleted # returns 1 if logical_card_id found # sub validate_active_rider_table_logical_card_id { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = "validate_active_rider_table_logical_card_id"; return 0 if !$logical_card_id; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'active_rider_table' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select max(seq_num) " . " from active_rider_table " . " where logical_card_id = ? "); $query->execute($logical_card_id); my $seq_num = $query->fetchrow_arrayref->[0]; $query = $self->prepare("select logical_card_id, ". " seq_num, " . " mag_token, " . " rfid_token, " . " deleted " . " from active_rider_table " . " where seq_num = ? "); $query->execute($seq_num); my $aref = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return 0 if !$aref; return 0 if $aref->[4]; return 1; } ########## sub validate_rule { my $self = shift; my $rule = shift; my $rule_param = shift; my $group_id = shift; my $FUNC_NAME = 'validate_rule'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'rule_mappings' => 'r', 'rule_class' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select rulename, " . " ruleclass " . " from rule_class " . " where rulename = ? " . " limit 1 "); $query->execute($rule); my $aref = $query->fetchrow_arrayref; if (!$aref) { $self->unlock_rollback() if $lock_local; return 0; } my $db_rule_name = $aref->[0]; my $db_rule_class = $aref->[1]; if ( lc($db_rule_class) eq 'nride') { if (!$rule_param or !($rule_param =~ m/^\d+\s*$/)) { $self->unlock_rollback() if $lock_local; return 0; } } elsif (lc($db_rule_class) eq 'nday') { if (!$rule_param or ( !($rule_param =~ m/^\d+\s*$/) && !($rule_param =~ m/^\d+ \d\d\d\d[-\/]\d?\d[-\/]\d?\d \d\d:\d\d:\d\d\s*$/) ) ) { $self->unlock_rollback() if $lock_local; return 0; } } if ($group_id) { $query = $self->prepare("select count(group_id) num " . " from rule_mappings " . " where rule = ? " . " and active = 1 " . " and (group_id = ? or group_id is null) " . " limit 1 "); $query->execute($db_rule_name, $group_id); if ($query->fetchrow_arrayref->[0] != 1) { $self->unlock_rollback() if $lock_local; return 0; } } $self->unlock_commit() if $lock_local; return 1; } ########## sub get_default_rule { my $self = shift; my $FUNC_NAME = 'get_default_rule'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'rule_mappings' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select rule " . " from rule_mappings " . " where group_id is null " . " limit 1"); $query->execute(); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0]; } ### sub get_rule_class { my $self = shift; my $rule = shift; my $FUNC_NAME = 'get_rule_class'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'rule_class' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select ruleclass " . " from rule_class " . " where rulename = ? "); $query->execute($rule); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; } ### sub insert_active_rider_table { my $self = shift; my $param_hash = shift; my $FUNC_NAME = "insert_active_rider_table"; return undef if !defined($param_hash->{'logical_card_id'}) or !$param_hash->{'logical_card_id'}; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->lock_common() if $lock_local; # $self->begin_locked_transaction_common() if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $default_rule = $self->get_default_rule(); my $query = $self->prepare(" select user_card.mag_token, " . " user_card.rfid_token, " . " user_card.group_id, " . " case when user_pass.rule is null then '" . $default_rule . "' " . " else user_pass.rule end, " . " user_pass.nrides_remain, " . " user_pass.nday_orig, " . " user_pass.nday_expiration, " . " user_pass.comment " . " from user_card left join user_pass " . " on (user_card.logical_card_id = user_pass.logical_card_id and" . " user_pass.active = 1) " . " where user_card.logical_card_id = ? " . " and user_card.active = 1 "); $query->execute( $param_hash->{'logical_card_id'} ); my $aref = $query->fetchrow_arrayref; # return undef if !$aref; if (!$aref) { $self->unlock_rollback() if $lock_local; return undef; } my @field = qw( logical_card_id rfid_token mag_token rule_name rule_param deleted ); my $rule = $aref->[3]; my $nride = $aref->[4]; my $nday = $aref->[5]; my $nday_exp = $aref->[6]; my $art_param = $aref->[7]; my $rule_type = $self->get_rule_class($rule); if (lc($rule_type) eq 'nride') { $art_param = $nride; } elsif (lc($rule_type) eq 'nday') { $art_param = $nday; if ($nday_exp) { $art_param .= " $nday_exp"; } } if ( !$self->validate_rule( $rule, $art_param ) ) { $self->unlock_rollback() if $lock_local; die "$PACKAGE_NAME: $FUNC_NAME: invalid logical_card_id, rule or rule_param ($rule, $nride, $nday, $nday_exp)"; } $query = $self->prepare("insert into active_rider_table ( " . join(', ', @field) . ") " . " values ( ?" . ", ?"x(scalar(@field)-1) . ") "); $query->execute($param_hash->{'logical_card_id'}, $aref->[1], $aref->[0], $rule, $art_param, 0); $self->unlock_commit() if $lock_local; return 1; } ### sub active_user_card_exists { my $self = shift; my $phash = shift; my $FUNC_NAME = 'active_user_card_exists'; my @fields = qw(MagToken MagStripe RFIDToken RFID CardId); my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'org_default_card_value' => 'r', 'user_card' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; foreach my $f (@fields) { next if $f =~ /^Group(Id|Name)$/; next if !$phash->{$f}; my $card_id; if ($phash->{GroupId}) { $card_id = $self->GetLogicalCardId( { $f => $phash->{$f}, GroupId => $phash->{GroupId} } ); } else { $card_id = $self->GetLogicalCardId( { $f => $phash->{$f} } ); } if ($card_id) { $self->unlock_commit() if $lock_local; return 1; } } $self->unlock_commit() if $lock_local; return undef; } ###### # # create a credential in database # 1) lock relevant tables (active_rider_table, user_card, user_pass, audit_user_card, audit_user_pass) # 2) insert into user_card # 3) insert into active_rider_table # 4) unlock tables # ###### #sub create_card sub CreateCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = "CreateCard"; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $phash->{GroupId} = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ) if (!$phash->{GroupId}); my %insert_param; while ( my ($k, $v) = each(%user_card_field_map) ) { $insert_param{$k} = $phash->{$v}; } $insert_param{'active'} = 1 if !defined($phash->{'Active'}); # default to active card $insert_param{'mag_token'} = $self->construct_mag_token( $phash ); $insert_param{'rfid_token'} = $self->construct_rfid_token( $phash ); if (!$insert_param{'group_id'}) { my %rhash; $self->GetDefaultCardGroupInfo(\%rhash, $phash); $insert_param{'group_id'} = $rhash{'GroupId'}; } if ($self->active_user_card_exists( $phash )) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Active card already exists"; return undef; } $rhash->{'CardId'} = $self->insert_user_card( \%insert_param ); if (!$rhash->{'CardId'}) { $rhash->{'Reason'} = "Insert Failed!"; $self->unlock_rollback() if $lock_local; return undef; } $self->insert_active_rider_table( { logical_card_id => $rhash->{'CardId'} } ); $self->unlock_commit() if $lock_local; return $rhash->{'CardId'}; } ################################ ## ## ## user_pass functions ## ## ################################ my %user_pass_field_map = ( user_pass_id => "PassId", logical_card_id => "CardId", issued => "Issued", firstused => "FirstUsed", lastused => "LastUsed", activated => "Activated", deactivated => "Deactivated", rule => "Rule", nrides_orig => "NRideOrig", nrides_remain => "NRideRemain", nday_orig => "NDayOrig", nday_expiration => "NDayExpiration", queue_order => "QueueOrder", comment => "Comment", active => "Active", expired => "Expired", paytype => "PaymentType", comment => "Comment" ); # # insert user pass helper function # issued defaults to now() # if active is set, activated defaults to now # sub insert_user_pass { my $self = shift; my $param_hash = shift; my $FUNC_NAME = "insert_user_pass"; my @field; my @val; my $query; my @default_field = ('issued', 'activated'); my @default_value = ('now()' , 'now()'); my @default_token; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'audit_user_pass' => 'w', 'user_pass' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # set defaults for (my $i=0; $i{$f})) { push @default_token, "?"; push @val, $param_hash->{$f}; } else { push @default_token, $default_value[$i]; } } # set value array foreach my $k (keys(%user_pass_field_map)) { next if grep $_ eq $k, @default_field; push @field, $k; push @val, (defined($param_hash->{$k}) ? $param_hash->{$k} : undef ); } my $audit_id = $self->audit_user_pass_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("insert into user_pass ( " . join(', ', @field) . ") " . "values ( " . join(', ', @default_token) . ", ?"x(scalar(@field)-scalar(@default_token)) . ")"); $query->execute(@val); my $pass_id = $self->last_insert_id(); $self->audit_user_pass_end($pass_id, $audit_id); $self->unlock_commit() if $lock_local; return $pass_id; } ### sub get_user_pass_logical_card_id { my $self = shift; my $pass_id = shift; my $FUNC_NAME = 'get_user_pass_logical_card_id'; return undef if !$pass_id; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_pass' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select logical_card_id " . " from user_pass " . " where user_pass_id = ? "); $query->execute($pass_id); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return $row->[0]; } #sub get_user_pass { sub GetUserPass { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetUserPass'; my ($query, $result); if ( !$phash->{'CardId'} and !$phash->{'PassId'} ) { $rhash->{'Reason'} = "Invalid Parameters"; return undef; } my $fields = "rule_class.ruleclass Type"; while ( my ($k, $v) = each(%user_pass_field_map) ) { $fields .= ", user_pass.$k $v"; } my @param; push @param, $phash->{'CardId'} if $phash->{'CardId'}; push @param, $phash->{'UserId'} if $phash->{'UserId'}; push @param, $phash->{'PassId'} if $phash->{'PassId'}; push @param, $phash->{'Active'} if $phash->{'Active'}; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_card' => 'r', 'user_pass' => 'r', 'rule_class' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select $fields " . " from user_pass, " . " user_card, " . " rule_class " . "where user_card.logical_card_id = user_pass.logical_card_id ". " and user_card.active = 1 " . " and user_pass.expired = 0 " . ( defined($phash->{'CardId'}) ? " and user_card.logical_card_id = ? " : "" ) . ( defined($phash->{'UserId'}) ? " and user_card.userid = ? " : "" ) . ( defined($phash->{'PassId'}) ? " and user_pass.user_pass_id = ? " : "") . ( defined($phash->{'Active'}) ? " and user_pass.active = ? " : "" ) . " and user_pass.rule = rule_class.rulename "); $query->execute(@param); my $row = $query->fetchrow_hashref; $self->unlock_commit() if $lock_local; if (!$row) { $rhash->{'Reason'} = "No Results"; return undef; } while ( my ($k, $v) = each(%$row) ) { $rhash->{$k} = $v; } return 1; } ### # #sub get_user_pass_old { # my $self = shift; # my $rhash = shift; # my $phash = shift; # # my ($query, $result); # # if (!$phash->{'PassId'}) # { # $rhash->{'Reason'} = "Invalid PassId"; # return undef; # } # # my $fields = "rule_class.ruleclass Type"; # while ( my ($k, $v) = each(%user_pass_field_map) ) # { # $fields .= ", user_pass.$k $v"; # } # # my @param; # push @param, $phash->{'PassId'}; # push @param, $phash->{'UserId'} if $phash->{'UserId'}; # # $query = # $self->prepare("select $fields " . # " from user_pass, " . # " user_card, " . # " rule_class " . # "where user_pass.user_pass_id = ? ". # " and user_card.logical_card_id = user_pass.logical_card_id ". # " and user_card.active = 1 " . # ( defined($phash->{'UserId'}) ? " and user_card.userid = ? " : "" ) . # " and user_pass.rule = rule_class.rulename "); # $query->execute(@param); # my $row = $query->fetchrow_hashref; # if (!$row) # { # $rhash->{'Reason'} = "Invalid UserId or PassId"; # return undef; # } # # while ( my ($k, $v) = each(%$row) ) # { # $rhash->{$k} = $v; # } # # return 1; # #} # ### #sub get_passes_on_card { sub GetPassesOnCard { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetPassesOnCard'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'org_default_card_value' => 'r', 'user_card' => 'r', 'user_pass' => 'r', 'rule_class' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $logical_card_id = $self->GetLogicalCardId($phash); my $fields = " case when rule_class.rulename is null then 'OTHER' " . " else rule_class.ruleclass end Type "; while ( my ($k, $v) = each(%user_pass_field_map) ) { $fields .= ", user_pass.$k $v"; } my $query = $self->prepare(" select $fields " . " from user_pass left join rule_class " . " on rule_class.rulename = user_pass.rule " . " where user_pass.logical_card_id = ? " . " and user_pass.expired = 0 " . " order by user_pass.queue_order asc "); my $result = $query->execute($logical_card_id); my $ind = ''; my $pos = 0; while (my $row = $query->fetchrow_hashref) { last if ($phash->{'MaxPass'} && ($pos >= $phash->{'MaxPass'})); while ( my ($k, $v) = each(%$row) ) { $rhash->{$k . $ind} = $v; } $ind = "[" . (++$pos) . "]"; } $rhash->{'NPass'} = '0'; $rhash->{'NPass'} = $pos if $pos; $self->unlock_commit() if $lock_local; return 1; } ### sub user_card_has_active_pass { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'user_card_has_active_pass'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_pass' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select count(user_pass_id) num " . " from user_pass " . " where logical_card_id = ? " . " and active = 1 " . " and expired = 0 " ); $query->execute($logical_card_id); $self->unlock_commit() if $lock_local; return ($query->fetchrow_arrayref->[0]==1); } ### sub activate_user_card_pass { my $self = shift; my $card_id = shift; my $FUNC_NAME = 'activate_user_card_pass'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_pass' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select min(queue_order) " . " from user_pass " . " where logical_card_id = ? " . " and expired = 0 "); $query->execute($card_id); my $q = $query->fetchrow_arrayref->[0]; if (!defined($q)) { $self->unlock_rollback() if $lock_local; return undef; } $query = $self->prepare("select user_pass_id " . " from user_pass " . " where logical_card_id = ? " . " and queue_order = ? "); $query->execute($card_id, $q); my $user_pass_id = $query->fetchrow_arrayref->[0]; $query = $self->prepare("update user_pass " . " set active = 1, " . " activated = now() " . " where user_pass_id = ? "); $query->execute($user_pass_id); $self->unlock_commit() if $lock_local; return 1; } #### sub user_card_pass_count { my $self = shift; my $card_id = shift; my $FUNC_NAME = 'user_card_pass_count'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_pass' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select count(user_pass_id) num " . " from user_pass " . "where logical_card_id = ? " . " and expired = 0 "); $query->execute($card_id); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0]; } ### sub get_next_queue_order { my $self = shift; my $logical_card_id = shift; my $FUNC_NAME = 'get_next_queue_order'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'user_pass' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select max(queue_order) num " . " from user_pass " . " where logical_card_id = ? "); $query->execute($logical_card_id); my $q = $query->fetchrow_arrayref->[0]; $self->unlock_commit() if $lock_local; return ( $q ? ($q+1) : 1 ); } ### sub RemovePass { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'RemovePass'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction_common() if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my %pass; my $r = $self->GetUserPass(\%pass, $phash); if ( (!$pass{PassId}) || (!$r) ) { $self->unlock_rollback() if $lock_local; $rhash->{Reason} = ($pass{Reason} || "Invalid PassId"); return undef; } my $pass_id = $pass{PassId}; my $card_id = $pass{CardId}; my $ret = $self->update_user_pass($pass_id, { active => 0, expired => 1, deactivated => unix_to_readable_time() } ); if ($pass{Active}) { $self->activate_user_card_pass($card_id); $self->insert_active_rider_table( { logical_card_id => $card_id } ); } $self->unlock_commit() if $lock_local; return 1; } ## sub deactivate_user_pass { my $self = shift; my $pass_id = shift; my $FUNC_NAME = "deactivate_user_pass"; return undef if !$pass_id; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'audit_user_pass' => 'w', 'user_pass' => 'w', 'user_card' => 'r', 'rule_class' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my %pass; # $self->get_user_pass(\%pass, { PassId => $pass_id }); $self->GetUserPass(\%pass, { PassId => $pass_id }); # return undef if (!$pass{'PassId'} or !$pass{'Active'}); if ((!$pass{'PassId'} or !$pass{'Active'})) { $self->unlock_rollback() if $lock_local; return undef; } # return $self->update_user_pass($pass_id, { active => 0, expired => 1, deactivated => unix_to_readable_time() } ); my $ret = $self->update_user_pass($pass_id, { active => 0, expired => 1, deactivated => unix_to_readable_time() } ); $self->unlock_commit() if $lock_local; # return $ret; return 1; } ### sub update_user_pass { my $self = shift; my $pass_id = shift; my $fields = shift; my $FUNC_NAME = "update_user_pass"; return undef if !$pass_id; my $str; my @val; while ( my ($k, $v) = each(%$fields) ) { next if (!$user_pass_field_map{$k}); $str .= " , " if $str; $str .= " $k = ? "; push @val, $v; } return undef if (scalar(@val)==0); my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'audit_user_pass' => 'w', 'user_pass' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $audit_id = $self->audit_user_pass_start($pass_id, "$PACKAGE_NAME: $FUNC_NAME"); my $query = $self->prepare("update user_pass set $str where user_pass_id = ? "); $query->execute(@val, $pass_id); $self->audit_user_pass_end($pass_id, $audit_id); $self->unlock_commit() if $lock_local; return 1; } #### #sub transfer_pass { sub TransferPass { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'TransferPass'; my $pass_id = $phash->{'PassId'}; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->lock_common() if $lock_local; # $self->begin_locked_transaction_common() if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $from_card_id = $self->get_user_pass_logical_card_id( $pass_id ); my $to_card_id = $self->GetDestLogicalCardId( $phash ); # $self->get_dest_logical_card_id( $phash ); if (!$from_card_id || !$to_card_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid Card (from id $from_card_id, to id $to_card_id)"; return undef; } my $queue_order = $self->get_next_queue_order($to_card_id); # move pass to new card $self->update_user_pass($pass_id, { logical_card_id => $to_card_id, queue_order => $queue_order, active => 0 } ); # if we removed an active pass, activate the current pass and update the art if ( !$self->user_card_has_active_pass($from_card_id) ) { if ($self->user_card_pass_count($from_card_id) > 0) { $self->activate_user_card_pass($from_card_id); } if (!$self->pending_card($from_card_id)) { $self->insert_active_rider_table( { logical_card_id => $from_card_id } ); } } # if we added an active pass, activate the current pass and update the art if ( !$self->user_card_has_active_pass($to_card_id) ) { if ($self->user_card_pass_count($to_card_id) > 0) { $self->activate_user_card_pass($to_card_id); } if (!$self->pending_card($to_card_id)) { $self->insert_active_rider_table( { logical_card_id => $to_card_id } ); } } $self->unlock_commit() if $lock_local; $rhash->{'PassId'} = $pass_id; return 1; } ### sub get_pass_type_and_name { my $self = shift; my $group_id = shift; my $type = shift; my $FUNC_NAME = 'get_pass_type_and_name'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'rule_class' => 'r', 'rule_mappings' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select rule_class.ruleclass, " . " rule_class.rulename " . " from rule_mappings, rule_class " . " where rule_mappings.group_id = ? " . " and rule_mappings.rule like ? " . " and rule_class.rulename = rule_mappings.rule " . " and rule_mappings.active = 1 "); $query->execute($group_id, '%-' . $type); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return undef if !$row; return ($row->[0], $row->[1]); } ### sub valid_pass_param { my $self = shift; my $pass_type = shift; my $phash= shift; my $FUNC_NAME = 'valid_pass_param'; return 0 if ( (lc($pass_type) eq 'nride') && (!$phash->{'NRideOrig'} || !$phash->{'NRideRemain'}) ); # !$phash->{'NRideOrig'} && !$phash->{'NRideRemain'} ); return 0 if ( (lc($pass_type) eq 'nride') && ($phash->{'NRideOrig'} < $phash->{'NRideRemain'}) ); return 0 if ( (lc($pass_type) eq 'nday') && !$phash->{'NDayOrig'} ); return 0 if ( (lc($pass_type) eq 'nday') && $phash->{'NDayExpiration'} && (!($phash->{'NDayExpiration'} =~ m/^\d\d\d\d[-\/]\d\d?[-\/]\d\d? *\d\d?:\d\d?:\d\d?$/)) ); return 1; } ### #sub add_pass { sub AddPass { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'AddPass'; my %blacklisted_fields = ( PassId => 1, Active => 1, Expired => 1 ); my $lock_local = ($self->lock_active() ? 0 : 1); # $self->lock_common() if $lock_local; # $self->begin_locked_transaction_common() if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; # my $logical_card_id = $self->GetLogicalCardId($phash); my $logical_card_id = $self->GetLogicalCardId( { CardId => $phash->{CardId}, MagTrack => $phash->{MagTrack}, MagStripe => $phash->{MagStripe}, MagToken=> $phash->{MagToken}, RFLength => $phash->{RFLength}, RFSite => $phash->{RFSite}, RFID => $phash->{RFID}, RFIDToken => $phash->{RFIDToken}, GroupId => $phash->{CardGroupId}, GroupName => $phash->{CardGroupName} } ); #my $group_id = $self->get_user_card_group_id($logical_card_id); my $group_id; if ($phash->{GroupId}) { $group_id = $phash->{GroupId}; } else { $group_id = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ); } if (!$logical_card_id || !$group_id) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid Card ($logical_card_id, $group_id)"; return undef; } my ($pass_type, $rule_name) = $self->get_pass_type_and_name($group_id, $phash->{'Type'}); if (!$pass_type || !$rule_name) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid rule"; return undef; } if ( !$self->valid_pass_param($pass_type, $phash) ) { $self->unlock_rollback() if $lock_local; $rhash->{'Reason'} = "Invalid rule/parameter combination for $pass_type"; ### DEBUG if (lc($pass_type) eq 'nday') { $rhash->{'Reason'} .= "(NDayOrig " . $phash->{NDayOrig} . ", NDay " . $phash->{NDay} . ", NDayExpiration " . $phash->{NDayExpiration} . ")"; } elsif (lc($pass_type) eq 'nride') { $rhash->{'Reason'} .= "(NRideOrig " . $phash->{NRideOrig} . ", NRideRemain" . $phash->{NRideRemain} . ")"; } ### DEBUG return undef; } my %insert_param; while ( my ($k, $v) = each(%user_pass_field_map) ) { next if !$phash->{$v} || $blacklisted_fields{$v}; $insert_param{$k} = $phash->{$v}; } $insert_param{'rule'} = $rule_name; $insert_param{'logical_card_id'} = $logical_card_id; $insert_param{'active'} = 0; $insert_param{'expired'} = 0; $insert_param{'queue_order'} = $self->get_next_queue_order($logical_card_id); my $pass_id = $self->insert_user_pass( \%insert_param ); if (!$self->pending_card($logical_card_id) && !$self->user_card_has_active_pass($logical_card_id)) { $self->activate_user_card_pass($logical_card_id); $self->insert_active_rider_table( { logical_card_id => $logical_card_id } ); } $self->unlock_commit() if $lock_local; $rhash->{'PassId'} = $pass_id; return 1; } ### my %pass_option_map = ( id => "PassOptionId", group_id => "GroupId", param => "Param", name => "Name", rule => "Rule", type => "Type", description => "Description", num_opt => "NumPassOption", option0 => "Option0", option1 => "Option1", option2 => "Option2", option3 => "Option3" ); my %default_pass_value_map = ( start => "Start", end => "Expiration", nday => "DefaultNDay", nride => "DefaultNRide" ); sub GetPassOptions { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetPassOptions'; my ($query, $row); my $group_inclusion; my @group_name; my @gruop_id; my $n; $n = $phash->{NGroup}; if (!$n) { $rhash->{Reason} = "Invalid NGroup"; return undef; } $group_inclusion = "(false "; for (my $i=0; $i<$n; $i++) { my $key = "GroupName"; $key = "${key}[$i]" if $i; push @group_name, $phash->{$key}; $group_inclusion .= " or groups.group_name = ? "; } $group_inclusion .= ")"; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare("select group_id from groups where $group_inclusion"); $query->execute(@group_name); $group_inclusion = "(false "; my @group_id; while ($row = $query->fetchrow_arrayref) { push @group_id, $row->[0]; $group_inclusion .= " or pass_option.group_id = ? "; } $group_inclusion .= ")"; $query = $self->prepare("select pass_option." . join(", pass_option.", keys(%pass_option_map) ) . " , " . " org_default_pass_value." . join(", org_default_pass_value.", keys(%default_pass_value_map)) . "," . " groups.group_name GroupName " . " from groups, pass_option left join org_default_pass_value " . " on ( pass_option.rule = org_default_pass_value.name " . " and pass_option.group_id = org_default_pass_value.group_id ) " . " where $group_inclusion " . " and pass_option.active = 1 " . " and groups.group_id = pass_option.group_id " . " order by pass_option.id "); $query->execute(@group_id); my $ind = ''; my $pos = 0; while ($row = $query->fetchrow_hashref) { while (my ($key, $val) = each(%pass_option_map)) { $rhash->{$val . $ind} = $row->{$key}; } while (my ($key, $val) = each(%default_pass_value_map)) { $rhash->{$val . $ind} = $row->{$key}; } $rhash->{"GroupName$ind"} = $row->{GroupName}; $ind = "[" . (++$pos) . "]"; } $rhash->{'NPassOption'} = $pos; $self->unlock_commit() if $lock_local; return 1; } #### my %price_point_map = ( id => "PricePointId", price => "Price", param => "Param", name => "Name", rule => "Rule", type => "Type", description => "Description", num_opt => "NumPriceOption", price_option0 => "PriceOption0", price_option1 => "PriceOption1", price_option2 => "PriceOption2", price_option3 => "PriceOption3" ); #### #sub get_price_points { sub GetPricePoints { my $self = shift; my $rhash = shift; my $phash = shift; my $FUNC_NAME = 'GetPricePoints'; my ($query, $row); my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $logical_card_id = $self->GetLogicalCardId($phash); my %group_hash; $self->GetDefaultCardGroupInfo(\%group_hash, $phash); my $group_id = $group_hash{'GroupId'}; my $group_name = $group_hash{'GroupName'}; if ($logical_card_id) { $query = $self->prepare("select user_card.group_id, " . " groups.group_name " . " from user_card, groups " . " where user_card.logical_card_id = ? " . " and groups.group_id = user_card.group_id " . " limit 1 "); $query->execute($logical_card_id); $row = $query->fetchrow_arrayref; if ($row) { $group_id = $row->[0]; $group_name = $row->[1]; } } $query = $self->prepare("select price_point." . join(", price_point.", keys(%price_point_map) ) . " , " . " org_default_pass_value." . join(", org_default_pass_value.", keys(%default_pass_value_map)) . " from price_point left join org_default_pass_value " . " on (price_point.name = org_default_pass_value.name) " . " where price_point.group_id = ? and price_point.active = 1 " . " order by price_point.id "); $query->execute($group_id); #$rhash->{'GroupId'} = $group_id; #$rhash->{'GroupName'} = $group_name; my $ind = ''; my $pos = 0; while ($row = $query->fetchrow_hashref) { while (my ($key, $val) = each(%price_point_map)) { $rhash->{$val . $ind} = $row->{$key}; } while (my ($key, $val) = each(%default_pass_value_map)) { $rhash->{$val . $ind} = $row->{$key}; } $rhash->{'GroupId' . $ind} = $group_id; $rhash->{'GroupName' . $ind} = $group_name; $ind = "[" . (++$pos) . "]"; } $rhash->{'NPricePoint'} = $pos; $self->unlock_commit() if $lock_local; return 1; } ### sub check_dup_billing_log { my $self = shift; my $unix_ts = shift; my $md5 = shift; my $FUNC_NAME = 'check_dup_billing_log'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'billing_log' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select count(*) num from billing_log where ride_time = FROM_UNIXTIME(?) and conf_checksum = ?"); my $r = $query->execute($unix_ts, $md5); $self->unlock_commit() if $lock_local; return $query->fetchrow_arrayref->[0] ; } ### sub insert_billing_log { my $self = shift; my $FUNC_NAME = 'insert_billing_log'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'billing_log' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("REPLACE INTO billing_log (conf_checksum, equip_num, driver, paddle, route, trip, stop, ride_time, latitude, longitude, action, rule, ruleparam, reason, credential, logical_card_id, cash_value, stop_name) VALUES (?, ?, ?, ?, ?, ?, ?, FROM_UNIXTIME(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); my $r = $query->execute(@_); $self->unlock_commit() if $lock_local; return $r; } ### sub diagnostic_log { my $self = shift; my $loglvl = shift; my $str = shift; my $FUNC_NAME = 'diagnostic_log'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'diagnostic_log' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $ins = $self->prepare("insert into diagnostic_log (loglvl, message) values (?, ?)"); my $ret = $ins->execute($loglvl, $str); $self->unlock_commit() if $lock_local; return $ret; } sub api_log { my $self = shift; my $msg = shift; my $FUNC_NAME = "api_log"; my $lock_local = ($self->lock_active() ? 0 : 1); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $ins = $self->prepare("insert into org_api_log (log) values (?)"); my $ret = $ins->execute($msg); $self->unlock_commit() if $lock_local; return $ret; } ### Admin specific functions sub admin_exists { my $self = shift; my $username = shift; my $FUNC_NAME = 'admin_exists'; my $lock_local = ($self->lock_active() ? 0 : 1); # $self->begin_locked_transaction( { 'admins' => 'r' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $query = $self->prepare("select username from admins where active = 1 and username = ? "); # and active = 1 "); $query->execute($username); my $row = $query->fetchrow_arrayref; $self->unlock_commit() if $lock_local; return 0 if !$row or ($row->[0] ne $username); return 1; } ## sub get_admin_id { my $self = shift; my $phash = shift; my $FUNC_NAME = 'get_admin_id'; my ($query, $result, $row); my $credential_match = " active = 1 "; my @credential_val; if ( defined($phash->{'UserName'}) ) { $credential_match .= " and username = ? "; push @credential_val , $phash->{'UserName'}; } if ( defined($phash->{'UserId'}) ) { $credential_match .= " and userid = ? "; push @credential_val, $phash->{'UserId'}; } if ( defined($phash->{'PasswordHash'}) ) { # $credential_match .= " and passwordhash = ? "; $credential_match .= " and password = ? "; push @credential_val, $phash->{'PasswordHash'}; } return undef if scalar(@credential_val)==0; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( { 'admins' => 'r' } ) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; $query = $self->prepare( "select userid " . " from admins " . " where $credential_match " . " limit 1 "); $result = $query->execute(@credential_val); $row = $query->fetchrow_arrayref; if (!$row) { $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; return $row->[0]; } ### sub CreateAdmin { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result); my $FUNC_NAME = "CreateAdmin"; my %blacklist_field = ( userid => 1 ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( { 'admins' => 'w', 'audit_admins' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; if ( !defined($phash->{'UserName'}) || $self->admin_exists($phash->{'UserName'}) ) { $rhash->{'Reason'} = "Invalid admin"; $self->unlock_rollback() if $lock_local; return undef; } my $group_id; if ($phash->{GroupId}) { $group_id = $phash->{GroupId}; } else { $group_id = $self->get_group_id( $phash->{GroupName} || $DEFAULT_GROUP_NAME ); } if (!$group_id) { $rhash->{Reason} = "Bad GroupId"; $self->unlock_rollback() if $lock_local; return undef; } my @db_field; my @param; while (my ($k, $v) = each(%admins_field_map) ) { next if ( $blacklist_field{lc($k)} ); push @db_field, $k; if ($v eq 'GroupId') { push @param, $group_id; } else { push @param, $phash->{$v}; } } my $audit_id = $self->audit_admins_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); my $query_str = "insert into admins " . " ( " . join(", ", @db_field) . " ) values " . " ( ? " . ", ?"x(scalar(@db_field)-1) . " )"; $query = $self->prepare($query_str); $result = $query->execute(@param); my $user_id = $self->last_insert_id(); $self->audit_admins_end($user_id, $audit_id); $query = $self->prepare("select userid, " . join(', ', @db_field) . " from admins where userid = ?"); $query->execute($user_id); my $href = $query->fetchrow_hashref; for (my $i=0; $i{$admins_field_map{$db_field[$i]}} = $href->{$db_field[$i]}; } $rhash->{'UserId'} = $href->{'userid'}; $self->unlock_commit() if $lock_local; return 1; } #### sub GetAdmin { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result); my $FUNC_NAME = "GetAdmin"; # my %blacklist_field = ( 'password' => 1 ); my %blacklist_field = ( ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $userid = $self->get_admin_id($phash); if (!$userid) { $rhash->{'Reason'} = "Invalid user credential"; $self->unlock_rollback() if $lock_local; return undef; } my $count=0; my $fields; while ( my ($k, $v) = each(%admins_field_map) ) { next if ( $blacklist_field{lc($k)} ); $fields .= ", " if ($count++); $fields .= " admins.$k $v "; } $query = $self->prepare("select groups.group_name GroupName, " . " $fields " . " from admins left join groups on (admins.group_id = groups.group_id) ". " where admins.userid = ? " . " and admins.active = 1 " . " limit 1"); $query->execute($userid); my $row = $query->fetchrow_hashref; if (!$row) { $rhash->{'Reason'} = "Invalid Admin"; $self->unlock_rollback() if $lock_local; return undef; } $self->unlock_commit() if $lock_local; while ( my ($k, $v) = each(%$row) ) { $rhash->{$k} = $v; } return 1; } ### sub SetAdmin { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result, $i, $j); my $FUNC_NAME= "SetAdmin"; my $update_fields; my @update_val; my %blacklist_field = ( username => 1, userid => 1 ); my $lock_local = ( $self->lock_active() ? 0 : 1 ); $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $userid = $self->get_admin_id( { UserName => $phash->{UserName}, UserId => $phash->{UserId} } ); if (!defined($userid)) { $rhash->{'Reason'} = "Invalid user credential"; $self->unlock_rollback() if $lock_local; return undef; } while ( my ($k, $v) = each(%admins_field_map) ) { next if $blacklist_field{lc($k)} || !exists($phash->{$v}); $update_fields .= ", " if $update_fields; $update_fields .= " $k = ? "; push @update_val, $phash->{$v}; } if (scalar(@update_val)==0) { $rhash->{'Reason'} = "Nothing to update"; $self->unlock_rollback() if $lock_local; return undef; } push @update_val, $userid; my $audit_id = $self->audit_admins_start($userid, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("update admins " . " set $update_fields " . " where userid = ?"); $result = $query->execute(@update_val); $self->audit_admins_end($userid, $audit_id ); $rhash->{'UserId'} = $userid; $self->unlock_commit() if $lock_local; return 1; } ### sub RemoveAdmin { my $self = shift; my $rhash = shift; my $phash = shift; my ($query, $result); my $FUNC_NAME = "RemoveAdmin"; my $lock_local = ( $self->lock_active() ? 0 : 1 ); # $self->begin_locked_transaction( { 'admins' => 'w', 'audit_admins' => 'w' }) if $lock_local; $self->begin_locked_transaction_for_function($FUNC_NAME) if $lock_local; my $user_id = $self->get_admin_id($phash); if (!$user_id) { $rhash->{'Reason'} = "Invalid user credential"; $self->unlock_rollback() if $lock_local; return undef; } my $audit_id = $self->audit_admins_start(undef, "$PACKAGE_NAME: $FUNC_NAME"); $query = $self->prepare("update admins set active = 0 where userid = ? "); $result = $query->execute($user_id); $self->audit_admins_end($user_id, $audit_id); $self->unlock_commit() if $lock_local; return 1; } return 1;