User activity tracking: ingress, auth.verify, and login agent
authorBill Erickson <berick@esilibrary.com>
Mon, 16 Jan 2012 21:24:54 +0000 (16:24 -0500)
committerThomas Berezansky <tsbere@mvlc.org>
Thu, 8 Mar 2012 18:50:06 +0000 (13:50 -0500)
Pile of user activity related additions:

* Set the global default Apache ingress value to 'apache'.  Overridable.
* Set the ingress value for remoteauth.cgi to 'remoteauth'
* Change remoteauth.cgi to use auth verify instead of true login
* Set ingress value for SIP to 'sip2'
* Set the ingress value for XMLRPC to 'xmlrpc'
* Set auth agent (ewho) to 'opac' for TPAC and JSPAC
* Set auth agent to 'staffclient' for staff client logins
* Set auth agent to 'authproxy' to the mod_perl Auth proxy
* Added support to the openils.User dojo class for auth verify and
  the login/verify "agent" parameter
* Set the auth agent to 'selfcheck' for the Selfcheck UI.  Also now using
  auth verify instead of login to check the patron username/barcode +
  password combination (when enforced).

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Thomas Berezansky <tsbere@mvlc.org>
Open-ILS/examples/apache/startup.pl
Open-ILS/examples/remoteauth.cgi
Open-ILS/src/perlmods/lib/OpenILS/SIP.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/Proxy.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/Proxy/Authen.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/XMLRPCGateway.pm
Open-ILS/web/js/dojo/openils/User.js
Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js
Open-ILS/web/opac/common/js/opac_utils.js
Open-ILS/xul/staff_client/chrome/content/auth/session.js

index ee9bb42..bb3fa16 100755 (executable)
@@ -1,4 +1,9 @@
 #!/usr/bin/perl
+use OpenSRF::AppSession;
+
+# default ingress value for all Apache/mod_perl clients
+OpenSRF::AppSession->ingress('apache'); 
+
 use OpenILS::WWW::Exporter qw( /openils/conf/opensrf_core.xml );
 use OpenILS::WWW::SuperCat qw( /openils/conf/opensrf_core.xml );
 use OpenILS::WWW::AddedContent qw( /openils/conf/opensrf_core.xml );
index 255f48c..67c7b5c 100755 (executable)
@@ -29,16 +29,19 @@ use Digest::MD5 qw(md5_hex);
 
 use OpenSRF::EX qw(:try);
 use OpenSRF::System;
+use OpenSRF::AppSession;
 
 my $bootstrap = '/openils/conf/opensrf_core.xml';
 my $cgi = new CGI;
 my $u = $cgi->param('user');
 my $usrname = $cgi->param('usrname');
 my $barcode = $cgi->param('barcode');
+my $agent = $cgi->param('agent'); # optional, but preferred
 my $p = $cgi->param('passwd');
 
 print $cgi->header(-type=>'text/html', -expires=>'-1d');
 
+OpenSRF::AppSession->ingress('remoteauth');
 OpenSRF::System->bootstrap_client( config_file => $bootstrap );
 
 if (!($u || $usrname || $barcode) || !$p) {
@@ -69,20 +72,17 @@ if (!($u || $usrname || $barcode) || !$p) {
        if ($seed) {
                my $response = OpenSRF::AppSession
                        ->create('open-ils.auth')
-                       ->request( 'open-ils.auth.authenticate.complete', { $nametype => $u, password => md5_hex($seed . md5_hex($p)), type => 'opac' })
+                       ->request( 'open-ils.auth.authenticate.verify', 
+                               { $nametype => $u, password => md5_hex($seed . md5_hex($p)), type => 'opac', agent => $agent })
                        ->gather(1);
-               if ($response->{payload}->{authtoken}) {
-                       my $user = OpenSRF::AppSession
-                               ->create('open-ils.auth')
-                               ->request( 'open-ils.auth.session.retrieve', $response->{payload}->{authtoken} )
-                               ->gather(1);
-                       if (ref($user) eq 'HASH' && $user->{ilsevent} == 1001) {
-                               print '+NO';
-                       } else {
+               if ($response) {
+                       if ($response->{ilsevent} == 0) {
                                print '+VALID';
+                       } else {
+                               print '+NO';
                        }
                } else {
-                       print '+NO';
+                       print '+BACKEND_ERROR';
                }
        } else {
                print '+BACKEND_ERROR';
index 3a82c79..4f62b1b 100644 (file)
@@ -17,6 +17,7 @@ use OpenILS::SIP::Transaction::Renew;
 use OpenILS::SIP::Transaction::FeePayment;
 
 use OpenSRF::System;
+use OpenSRF::AppSession;
 use OpenILS::Utils::Fieldmapper;
 use OpenSRF::Utils::SettingsClient;
 use OpenILS::Application::AppUtils;
@@ -47,6 +48,9 @@ sub new {
        $target_encoding = $institution->{implementation_config}->{encoding} || 'ascii';
 
        syslog('LOG_DEBUG', "OILS: loading bootstrap config: $bsconfig");
+
+       # ingress will persist throughout
+       OpenSRF::AppSession->ingress('sip2');
        
        local $/ = "\n";    # why?
        OpenSRF::System->bootstrap_client(config_file => $bsconfig);
index a0413c6..b1ffd40 100644 (file)
@@ -330,7 +330,8 @@ sub load_login {
     my $args = {       
         username => $username, 
         password => md5_hex($seed . md5_hex($password)), 
-        type => ($persist) ? 'persist' : 'opac' 
+        type => ($persist) ? 'persist' : 'opac',
+        agent => 'opac'
     };
 
     my $bc_regex = $ctx->{get_org_setting}->($org_unit, 'opac.barcode_regex');
index 6c5f3da..ee7b4ef 100644 (file)
@@ -185,7 +185,7 @@ sub oils_login {
         my $response = OpenSRF::AppSession
                ->create("open-ils.auth")
                ->request( 'open-ils.auth.authenticate.complete',
-                       { $nametype => $username,
+                       { $nametype => $username, agent => 'authproxy',
                          password => md5_hex($seed . md5_hex($password)),
                          type => $type })
                ->gather(1);
index e8962a3..d6ca65e 100644 (file)
@@ -163,7 +163,7 @@ sub oils_login {
         my $response = OpenSRF::AppSession
                ->create("open-ils.auth")
                ->request( 'open-ils.auth.authenticate.complete',
-                       { $nametype => $username,
+                       { $nametype => $username, agent => 'authproxy',
                          password => md5_hex($seed . md5_hex($password)),
                          type => $type })
                ->gather(1);
index ea80f1d..26eb0a7 100644 (file)
@@ -40,6 +40,7 @@ sub import { $bs_config = $_[1]; }
 # Bootstrap and load config settings
 sub child_init {
        $__inited = 1;
+       OpenSRF::AppSession->ingress('xmlrpc');
        OpenSRF::System->bootstrap_client( config_file => $bs_config );
        my $sclient     = OpenSRF::Utils::SettingsClient->new();
        my $idl = $sclient->config_value("IDL");
@@ -48,6 +49,7 @@ sub child_init {
        $logger->debug("XML-RPC: allowed services @$services");
        OpenILS::Utils::Fieldmapper->require;
        Fieldmapper->import(IDL => $idl);
+       OpenSRF::AppSession->ingress('apache');
 }
 
 
@@ -82,8 +84,12 @@ sub handler {
 
 sub run_request {
     my( $service, $method, @args ) = @_;
+
+    # since multiple Perl clients run within mod_perl, 
+    # we must set our ingress before each request.
+    OpenSRF::AppSession->ingress('xmlrpc');
+
     my $ses = OpenSRF::AppSession->create( $service );
-    #my $data = $ses->request($method, @args)->gather(1);
 
     my $data = [];
     my $req = $ses->request($method, @args);
@@ -95,6 +101,10 @@ sub run_request {
         push( @$data, $resp->content );
     }
 
+    # recover the default Apache/http ingress to avoid 
+    # polluting other mod_perl clients w/ our ingress value.
+    OpenSRF::AppSession->ingress('apache');
+
     return [] if scalar(@$data) == 0;
     return wrap_perl($$data[0]) 
         if scalar(@$data) == 1 and $method !~ /.atomic$/og;
index bd91ba8..60e5f91 100644 (file)
@@ -33,6 +33,7 @@ if(!dojo._hasResource["openils.User"]) {
         username : null,
         passwd : null,
         login_type : 'opac',
+        login_agent : null,
         location : null,
         authtoken : null,
         authtime : null,
@@ -48,6 +49,7 @@ if(!dojo._hasResource["openils.User"]) {
             this.authtoken = kwargs.authtoken || openils.User.authtoken;
             this.authtime = kwargs.authtime || openils.User.authtime;
             this.login_type = kwargs.login_type;
+            this.login_agent = kwargs.login_agent || openils.User.default_login_agent || 'staffclient';
             this.location = kwargs.location;
             this.authcookie = kwargs.authcookie || openils.User.authcookie;
             this.permOrgStoreCache = {}; /* permName => permOrgUnitStore map */
@@ -111,6 +113,42 @@ if(!dojo._hasResource["openils.User"]) {
                 return req.recv().content();
             }
         },
+
+        /**
+         * Tests the given username and password.  This version is async only.
+         */
+        auth_verify : function(args, onComplete) {
+            var _u = this;
+            if (!args) args = {};
+            if (!args.username) args.username = _u.username;
+            if (!args.passwd) args.passwd = _u.passwd;
+            if (!args.agent) args.agent = _u.login_agent;
+            if (!args.type) args.type = _u.type;
+
+            var initReq = OpenSRF.CachedClientSession('open-ils.auth').request('open-ils.auth.authenticate.init', args.username);
+    
+            initReq.oncomplete = function(r) {
+                var seed = r.recv().content(); 
+                var loginInfo = {
+                    type : args.type,
+                    username : args.username,
+                    barcode : args.barcode,
+                    password : hex_md5(seed + hex_md5(args.passwd)), 
+                    agent : args.agent,
+                };
+    
+                var authReq = OpenSRF.CachedClientSession('open-ils.auth').request('open-ils.auth.authenticate.verify', loginInfo);
+                authReq.oncomplete = function(rr) {
+                    var data = rr.recv().content();
+                    var evt = openils.Event.parse(data);
+                    if (evt && evt.code == 0) onComplete(true);
+                    else onComplete(false);
+                }
+                authReq.send();
+            }
+    
+            initReq.send();
+        },
     
     
         /**
@@ -123,6 +161,7 @@ if(!dojo._hasResource["openils.User"]) {
             if (!args.username) args.username = _u.username;
             if (!args.passwd) args.passwd = _u.passwd;
             if (!args.type) args.type = _u.login_type;
+            if (!args.agent) args.agent = _u.login_agent;
             if (!args.location) args.location = _u.location;
 
             var initReq = OpenSRF.CachedClientSession('open-ils.auth').request('open-ils.auth.authenticate.init', args.username);
@@ -133,6 +172,7 @@ if(!dojo._hasResource["openils.User"]) {
                     username : args.username,
                     password : hex_md5(seed + hex_md5(args.passwd)), 
                     type : args.type,
+                    agent : args.agent,
                     org : args.location,
                     workstation : args.workstation
                 };
@@ -165,6 +205,7 @@ if(!dojo._hasResource["openils.User"]) {
             if (!args.username) args.username = _u.username;
             if (!args.passwd) args.passwd = _u.passwd;
             if (!args.type) args.type = _u.login_type;
+            if (!args.agent) args.agent = _u.login_agent;
             if (!args.location) args.location = _u.location;
 
             var seed = fieldmapper.standardRequest(
@@ -176,6 +217,7 @@ if(!dojo._hasResource["openils.User"]) {
                 username : args.username,
                 password : hex_md5(seed + hex_md5(args.passwd)), 
                 type : args.type,
+                agent : args.agent,
                 org : args.location,
                 workstation : args.workstation,
             };
@@ -298,6 +340,7 @@ if(!dojo._hasResource["openils.User"]) {
        openils.User.authtoken = null;
        openils.User.authtime = null;
     openils.User.authcookie = null;
+    openils.User.default_login_agent = null; // global agent override
     openils.User.localeStrings =
         dojo.i18n.getLocalization("openils.User", "User");
 
index 882c980..886c8c3 100644 (file)
@@ -27,6 +27,9 @@ const SET_CC_PAYMENT_ALLOWED = 'credit.payments.allow';
 // This setting only comes into play if COPY_NOT_AVAILABLE is in the SET_AUTO_OVERRIDE_EVENTS list
 const SET_BLOCK_CHECKOUT_ON_COPY_STATUS = 'circ.selfcheck.block_checkout_on_copy_status';
 
+// set before the login dialog is rendered
+openils.User.default_login_agent = 'selfcheck';
+
 function SelfCheckManager() {
 
     this.cgi = new openils.CGI();
@@ -329,21 +332,31 @@ SelfCheckManager.prototype.loginPatron = function(barcode_or_usrname, passwd) {
 
         // patron password is required.  Verify it.
 
-        var res = fieldmapper.standardRequest(
-            ['open-ils.actor', 'open-ils.actor.verify_user_password'],
-            {params : [this.authtoken, barcode, usrname, hex_md5(passwd)]}
+        var self = this;
+        new openils.User().auth_verify(
+            {   username : usrname, barcode : barcode, 
+                type : 'opac', passwd : passwd, agent : 'selfcheck' },
+            function(OK) {
+                if (OK) {
+                    self.fetchPatron(barcode, usrname);
+
+                } else {
+                    // auth verify failed
+                    self.handleAlert(
+                        dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode_or_usrname]),
+                        false, 'login-failure'
+                    );
+                    self.drawLoginPage();
+                }
+            }
         );
 
-        if(res == 0) {
-            // user-not-found results in login failure
-            this.handleAlert(
-                dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode_or_usrname]),
-                false, 'login-failure'
-            );
-            this.drawLoginPage();
-            return;
-        }
-    } 
+    } else {
+        this.fetchPatron(barcode, usrname);
+    }
+};
+
+SelfCheckManager.prototype.fetchPatron = function(barcode, usrname) {
 
     var patron_id = fieldmapper.standardRequest(
         ['open-ils.actor', 'open-ils.actor.user.retrieve_id_by_barcode_or_username'],
@@ -373,7 +386,7 @@ SelfCheckManager.prototype.loginPatron = function(barcode_or_usrname, passwd) {
 
     if(evt || inactiveCard) {
         this.handleAlert(
-            dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode_or_usrname]),
+            dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode || usrname]),
             false, 'login-failure'
         );
         this.drawLoginPage();
index b699f46..bf1f3d6 100644 (file)
@@ -727,7 +727,8 @@ function doLogin(suppressEvents) {
        var args = {
                password : hex_md5(seed + hex_md5(passwd)), 
                type            : "opac", 
-               org             : getOrigLocation()
+               org             : getOrigLocation(),
+               agent : 'opac'
        };
 
     r = fetchOrgSettingDefault(globalOrgTree.id(), 'opac.barcode_regex');
index c3f9a13..c4f0ae8 100644 (file)
@@ -38,6 +38,7 @@ auth.session.prototype = {
                         )
                     ),
                     'type' : 'temp',
+                    'agent' : 'staffclient'
                 };
 
                 if (data.ws_info[ this.view.server_prompt.value ]) {