updates for the perm editor -- FM dance required
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 23 Jan 2006 23:45:14 +0000 (23:45 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 23 Jan 2006 23:45:14 +0000 (23:45 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@2802 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/permission.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/actor.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/permission.pm
Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm
Open-ILS/src/sql/Pg/006.schema.permissions.sql
Open-ILS/xul/staff_client/server/patron/user_edit.js
Open-ILS/xul/staff_client/server/patron/user_edit.xml
OpenSRF/src/perlmods/OpenSRF/Application.pm

index d7cd0b2..eb4c01f 100644 (file)
@@ -202,8 +202,6 @@ sub update_patron {
                }
        }
 
-       $apputils->commit_db_session($session);
-
        $session = OpenSRF::AppSession->create("open-ils.storage");
        $new_patron     = _create_stat_maps($session, $user_session, $patron, $new_patron, $user_obj);
        if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
@@ -212,6 +210,14 @@ sub update_patron {
                return undef;
        }
 
+       $new_patron     = _create_perm_maps($session, $user_session, $patron, $new_patron, $user_obj);
+       if(UNIVERSAL::isa($new_patron, "OpenILS::EX") || 
+               UNIVERSAL::isa($new_patron, "OpenILS::Perm")) {
+               $client->respond_complete($new_patron->ex);
+               return undef;
+       }
+
+       $apputils->commit_db_session($session);
 
        warn "Patron Update/Create complete\n";
        return flesh_user($new_patron->id());
@@ -626,6 +632,43 @@ sub _create_stat_maps {
        return $new_patron;
 }
 
+sub _create_perm_maps {
+
+       my($session, $user_session, $patron, $new_patron) = @_;
+
+       my $maps = $patron->permissions;
+
+       for my $map (@$maps) {
+
+               my $method = "open-ils.storage.direct.permission.usr_perm_map.update";
+               if ($map->isdeleted()) {
+                       $method = "open-ils.storage.direct.permission.usr_perm_map.delete";
+               } elsif ($map->isnew()) {
+                       $method = "open-ils.storage.direct.permission.usr_perm_map.create";
+                       $map->clear_id;
+               }
+
+
+               $map->usr($new_patron->id);
+
+               warn( "Updating permissions with method $method and session $user_session and map $map" );
+               $logger->debug( "Updating permissions with method $method and session $user_session and map $map" );
+
+               my $req = $session->request($method, $map);
+               my $status = $req->gather(1);
+
+               warn "Updated\n";
+
+               if(!$status) {
+                       throw OpenSRF::EX::ERROR 
+                               ("Error updating permission map with method $method");  
+               }
+
+       }
+
+       return $new_patron;
+}
+
 
 
 __PACKAGE__->register_method(
@@ -1274,6 +1317,44 @@ sub user_transactions {
 
 
 __PACKAGE__->register_method(
+       method  => "user_perms",
+       api_name        => "open-ils.actor.permissions.user_perms.retrieve",
+       argc            => 1,
+       notes           => <<"  NOTES");
+       Returns a list of permissions
+       NOTES
+sub user_perms {
+       my( $self, $client, $authtoken, $user ) = @_;
+
+       my( $staff, $evt ) = $apputils->checkses($authtoken);
+       return $evt if $evt;
+
+       $user ||= $staff->id;
+
+       if( $user != $staff->id and $evt = $apputils->check_perms( $staff->id, $staff->home_ou, 'VIEW_PERMISSION') ) {
+               return $evt;
+       }
+
+       return $apputils->simple_scalar_request(
+               "open-ils.storage",
+               "open-ils.storage.permission.user_perms.atomic",
+               $user);
+}
+
+__PACKAGE__->register_method(
+       method  => "retrieve_perms",
+       api_name        => "open-ils.actor.permissions.retrieve",
+       notes           => <<"  NOTES");
+       Returns a list of permissions
+       NOTES
+sub retrieve_perms {
+       my( $self, $client ) = @_;
+       return $apputils->simple_scalar_request(
+               "open-ils.storage",
+               "open-ils.storage.direct.permission.perm_list.retrieve.all.atomic");
+}
+
+__PACKAGE__->register_method(
        method  => "retrieve_groups",
        api_name        => "open-ils.actor.groups.retrieve",
        notes           => <<"  NOTES");
index 5c6c9cc..fa856a1 100644 (file)
@@ -23,12 +23,12 @@ __PACKAGE__->columns(All => qw/id usr grp/);
 package permission::usr_perm_map;
 use base qw/permission/;
 __PACKAGE__->table('permission_usr_perm_map');
-__PACKAGE__->columns(All => qw/id usr perm depth/);
+__PACKAGE__->columns(All => qw/id usr perm depth grantable/);
 #-------------------------------------------------------------------------------
 package permission::grp_perm_map;
 use base qw/permission/;
 __PACKAGE__->table('permission_grp_perm_map');
-__PACKAGE__->columns(All => qw/id grp perm depth/);
+__PACKAGE__->columns(All => qw/id grp perm depth grantable/);
 #-------------------------------------------------------------------------------
 1;
 
index 88f3379..dee1361 100644 (file)
@@ -375,6 +375,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                        api_name        => $api_prefix.'.search',
                        method          => 'search',
                        api_level       => 1,
+                       argc            => 2,
                        stream          => 1,
                        cdbi            => $cdbi,
                        cachable        => 1,
@@ -387,6 +388,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                        method          => 'search_where',
                        api_level       => 1,
                        stream          => 1,
+                       argc            => 1,
                        cdbi            => $cdbi,
                        cachable        => 1,
                );
@@ -400,6 +402,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                        stream          => 1,
                        cdbi            => $cdbi,
                        cachable        => 1,
+                       argc            => 2,
                );
        }
 
@@ -412,6 +415,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                stream          => 1,
                                cdbi            => $cdbi,
                                cachable        => 1,
+                               argc            => 2,
                        );
                }
        }
@@ -425,6 +429,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                stream          => 1,
                                cdbi            => $cdbi,
                                cachable        => 1,
+                               argc            => 2,
                        );
                }
        }
@@ -438,6 +443,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                stream          => 1,
                                cdbi            => $cdbi,
                                cachable        => 1,
+                               argc            => 2,
                        );
                }
        }
@@ -450,6 +456,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                        api_level       => 1,
                        cdbi            => $cdbi,
                        cachable        => 1,
+                       argc            => 1,
                );
        }
 
@@ -462,6 +469,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                        stream          => 1,
                        cdbi            => $cdbi,
                        cachable        => 1,
+                       argc            => 1,
                );
        }
 
@@ -474,6 +482,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                cdbi            => $cdbi,
                                cachable        => 1,
                                stream          => 1,
+                               argc            => 1,
                        );
                }
                unless ( __PACKAGE__->is_registered( $api_prefix.'.search_like.'.$field ) ) {
@@ -484,6 +493,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                cdbi            => $cdbi,
                                cachable        => 1,
                                stream          => 1,
+                               argc            => 1,
                        );
                }
                if (\&Class::DBI::search_fts) {
@@ -495,6 +505,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                        cdbi            => $cdbi,
                                        cachable        => 1,
                                        stream          => 1,
+                                       argc            => 1,
                                );
                        }
                }
@@ -507,6 +518,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                        cdbi            => $cdbi,
                                        cachable        => 1,
                                        stream          => 1,
+                                       argc            => 1,
                                );
                        }
                }
@@ -519,6 +531,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                        cdbi            => $cdbi,
                                        cachable        => 1,
                                        stream          => 1,
+                                       argc            => 1,
                                );
                        }
                }
@@ -533,6 +546,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'create_node',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -543,6 +557,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'batch_call',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -553,6 +568,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'update_node',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -563,6 +579,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'batch_call',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -573,6 +590,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'delete_node',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -583,6 +601,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'batch_call',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -593,6 +612,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'merge_node',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -604,6 +624,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                unwrap          => 1,
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -614,6 +635,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'remote_update_node',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -625,6 +647,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                api_level       => 1,
                                unwrap          => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
 
@@ -635,6 +658,7 @@ for my $fmclass ( (Fieldmapper->classes) ) {
                                method          => 'mass_delete',
                                api_level       => 1,
                                cdbi            => $cdbi,
+                               argc            => 1,
                        );
                }
        }
index 8391203..738649c 100644 (file)
@@ -285,7 +285,12 @@ sub org_unit_ancestors {
 
        my $func = 'actor.org_unit_ancestors(?)';
 
-       my $sth = actor::org_unit->db_Main->prepare_cached("SELECT * FROM $func");
+       my $sth = actor::org_unit->db_Main->prepare_cached(<<"  SQL");
+               SELECT  f.*
+                 FROM  $func f
+                       JOIN actor.org_unit_type t ON (f.ou_type = t.id)
+                 ORDER BY t.depth, f.name;
+       SQL
        $sth->execute(''.$id);
 
        $client->respond( $_->to_fieldmapper ) for ( map { actor::org_unit->construct($_) } $sth->fetchall_hash );
index c03c9d6..1fb49a1 100644 (file)
@@ -16,7 +16,24 @@ sub retrieve_all {
 __PACKAGE__->register_method(
        method          => 'retrieve_all',
        api_name        => 'open-ils.storage.direct.permission.grp_tree.retrieve.all',
-       argc            => 3,
+       argc            => 0,
+       stream          => 1,
+);
+
+sub retrieve_perms {
+       my $self = shift;
+       my $client = shift;
+
+       for my $rec ( sort { $a->code cmp $b->code } permission::perm_list->retrieve_all ) {
+               $client->respond( $rec->to_fieldmapper );
+       }
+
+       return undef;
+}
+__PACKAGE__->register_method(
+       method          => 'retrieve_perms',
+       api_name        => 'open-ils.storage.direct.permission.perm_list.retrieve.all',
+       argc            => 0,
        stream          => 1,
 );
 
@@ -52,7 +69,7 @@ sub usr_perms {
 __PACKAGE__->register_method(
        method          => 'usr_perms',
        api_name        => 'open-ils.storage.permission.user_perms',
-       argc            => 2,
+       argc            => 1,
        stream          => 1,
 );
 
index dbc1267..e73b12c 100644 (file)
@@ -90,6 +90,7 @@ sub _init {
                                                                                             checkouts          => 1,
                                                                                             hold_requests      => 1,
                                                                                             settings           => 1,
+                                                                                            permissions        => 1,
                                                                                             addresses          => 1 } },
                'Fieldmapper::actor::user_setting'              => { hint => 'aus'    },
                'Fieldmapper::actor::org_unit_setting'          => { hint => 'aous'    },
index 9cecfb7..00c7f18 100644 (file)
@@ -67,10 +67,11 @@ INSERT INTO permission.grp_tree VALUES (5, 'Circulators', 3);
 SELECT SETVAL('permission.grp_tree_id_seq'::TEXT, 6);
 
 CREATE TABLE permission.grp_perm_map (
-       id      SERIAL  PRIMARY KEY,
-       grp     INT     NOT NULL REFERENCES permission.grp_tree (id) ON DELETE CASCADE,
-       perm    INT     NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE,
-       depth   INT     NOT NULL,
+       id              SERIAL  PRIMARY KEY,
+       grp             INT     NOT NULL REFERENCES permission.grp_tree (id) ON DELETE CASCADE,
+       perm            INT     NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE,
+       depth           INT     NOT NULL,
+       grantable       BOOL    NOT NULL DEFAULT FALSE,
                CONSTRAINT perm_grp_once UNIQUE (grp,perm)
 );
 
@@ -111,10 +112,11 @@ SELECT SETVAL('permission.grp_perm_map_id_seq'::TEXT, 48);
 
 
 CREATE TABLE permission.usr_perm_map (
-       id      SERIAL  PRIMARY KEY,
-       usr     INT     NOT NULL REFERENCES actor.usr (id) ON DELETE CASCADE,
-       perm    INT     NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE,
-       depth   INT     NOT NULL,
+       id              SERIAL  PRIMARY KEY,
+       usr             INT     NOT NULL REFERENCES actor.usr (id) ON DELETE CASCADE,
+       perm            INT     NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE,
+       depth           INT     NOT NULL,
+       grantable       BOOL    NOT NULL DEFAULT FALSE,
                CONSTRAINT perm_usr_once UNIQUE (usr,perm)
 );
 
@@ -159,7 +161,7 @@ BEGIN
                                )
                LOOP
 
-               FOR u_perm IN   SELECT  DISTINCT -p.id, iuser AS usr, p.perm, p.depth
+               FOR u_perm IN   SELECT  DISTINCT -p.id, iuser AS usr, p.perm, p.depth, p.grantable
                                  FROM  permission.grp_perm_map p
                                  WHERE p.grp = g_list.id LOOP
 
@@ -175,7 +177,7 @@ BEGIN
                FOR g_list IN   SELECT  *
                                  FROM  permission.grp_ancestors( grp.grp ) LOOP
 
-                       FOR u_perm IN   SELECT  DISTINCT -p.id, iuser AS usr, p.perm, p.depth
+                       FOR u_perm IN   SELECT  DISTINCT -p.id, iuser AS usr, p.perm, p.depth, p.grantable
                                          FROM  permission.grp_perm_map p
                                                JOIN permission.usr_grp_map m ON (m.grp = p.grp)
                                          WHERE m.grp = g_list.id LOOP
index 5763851..cc2e02f 100644 (file)
@@ -3,6 +3,10 @@ var orgTree;
 var user;
 var ses_id;
 var user_groups = [];
+var adv_items = [];
+var user_perms = [];
+var perm_list = [];
+
 
 var required_user_parts = {
        usrname:'User Name',
@@ -26,6 +30,47 @@ var required_addr_parts = {
        address_type:'Address Label',
 };
 
+function set_perm(row) {
+       var pid = findNodeByName(row,'p.code').getAttribute('permid');
+       var papply = findNodeByName(row,'p.id').checked;
+       var pdepth = findNodeByName(row,'p.depth').options[findNodeByName(row,'p.depth').selectedIndex].value;
+       var pgrant = findNodeByName(row,'p.grantable').checked;
+
+       var p;
+       for (var i in user_perms) {
+               if (user_perms[i].perm() == pid) {
+                       p = user_perms[i];
+                       if (papply) {
+                               p.isdeleted(0);
+                               p.ischanged(1);
+                               p.depth(pdepth);
+                               p.grantable(pgrant ? 1 : 0);
+                       } else {
+                               if (p.isnew()) {
+                                       user_perms[i] = null;
+                               } else {
+                                       p.isdeleted(1);
+                               }
+                       }
+                       break;
+               }
+       }
+
+       if (!p) {
+               if (papply) {
+                       p = new pupm();
+                       p.isnew(1);
+                       p.perm(pid);
+                       p.usr(user.id());
+                       p.depth('' + pdepth);
+                       p.grantable(pgrant ? 1 : 0);
+
+                       user_perms.push(p);
+               }
+       }
+
+}
+
 function reset_crc () {
        document.forms.editor.elements["user.claims_returned_count"].value = '0';
        user.claims_returned_count(0);
@@ -44,6 +89,21 @@ function save_user () {
 
        try {
 
+               for (var i in user_perms) {
+                       if (!user_perms[i].depth()) {
+                               var p;
+                               for (var j in perm_list) {
+                                       if (perm_list[j].id() == user_perms[i].perm()) {
+                                               p = perm_list[j];
+                                               break;
+                                       }
+                               }
+                               throw "Depth is required on the " + p.code() + " permission.";
+                       }
+               }
+
+               user.permissions(user_perms);
+
                for (var i in required_user_parts) {
                        if (!user[i]()) {
                                throw required_user_parts[i] + " is required.";
@@ -113,12 +173,26 @@ function fakeid () {
        return --_fake_id;
 };
 
+var adv_mode = false;
+function apply_adv_mode (root) {
+       adv_items = findNodesByClass(root,'advanced');
+       for (var i in adv_items) {
+               adv_mode ?
+                       removeCSSClass(adv_items[i], 'hideme') :
+                       addCSSClass(adv_items[i], 'hideme');
+       }
+}
+
 function init_editor (u) {
        
        var x = document.getElementById('editor').elements;
 
+       
+       cgi = new CGI();
+       if (cgi.param('adv')) adv_mode = true;
+       apply_adv_mode(document.getElementById('editor'));
+
        if (!u) {
-               cgi = new CGI();
                ses_id = cgi.param('ses');
 
                var usr_id = cgi.param('usr');
@@ -235,7 +309,7 @@ function init_editor (u) {
        // onchange handled by func above
 
        if (user.alert_message()) x['user.alert_message'].value = user.alert_message();
-       // onchange handled by func above
+       x['user.alert_message'].setAttribute('onchange','user.alert_message(this.value)');
 
 
        // set up the home_ou selector
@@ -365,12 +439,100 @@ function init_editor (u) {
        surveys = req.getResultObject();
 
        var f = document.getElementById('surveys');
+       while (f.firstChild) f.removeChild(f.lastChild);
+
        for ( var i in surveys )
                display_survey( f, surveys[i].id(), user.id() );
 
+       req = new RemoteRequest( 'open-ils.actor', 'open-ils.actor.permissions.user_perms.retrieve', ses_id );
+       req.send(true);
+       var staff_perms = req.getResultObject();
+
+       user_perms = [];
+       req = new RemoteRequest( 'open-ils.actor', 'open-ils.actor.permissions.user_perms.retrieve', ses_id, user.id() );
+       req.send(true);
+       var up = req.getResultObject();
+       for (var i in up) {
+               if (up[i].id() > 0)
+                       user_perms.push(up[i]);
+       }
+
+       req = new RemoteRequest( 'open-ils.actor', 'open-ils.actor.permissions.retrieve' );
+       req.send(true);
+       perm_list = req.getResultObject();
+
+       f = document.getElementById('permissions');
+       while (f.firstChild) f.removeChild(f.lastChild);
+
+       for (var i in perm_list)
+               display_perm(f,perm_list[i],staff_perms);
+
        return true;
 }
 
+function display_perm (root,perm_def,staff_perms) {
+
+       var prow = findNodeByName(document.getElementById('permission-tmpl'), 'prow').cloneNode(true);
+       root.appendChild(prow);
+
+       var all = false;
+       for (var i in staff_perms) {
+               if (staff_perms[i].perm() == -1) {
+                       all = true;
+                       break;
+               }
+       }
+
+
+       var sp,up;
+       if (!all) {
+               for (var i in staff_perms) {
+                       if (perm_def.id() == staff_perms[i].perm() || staff_perms[i].perm() == -1) {
+                               sp = staff_perms[i];
+                               break;
+                       }
+               }
+       }
+
+       for (var i in user_perms) {
+               if (perm_def.id() == user_perms[i].perm() && user_perms[i].id() > 0)
+                       up = user_perms[i];
+       }
+
+
+       var dis = false;
+       if (!sp || !sp.grantable()) dis = true; 
+       if (all) dis = false; 
+
+       var label_cell = findNodeByName(prow,'plabel');
+       findNodeByName(label_cell,'p.code').appendChild(text(perm_def.code()));
+       findNodeByName(label_cell,'p.code').setAttribute('title', perm_def.description());
+       findNodeByName(label_cell,'p.code').setAttribute('permid', perm_def.id());
+
+       var apply_cell = findNodeByName(prow,'papply');
+       findNodeByName(apply_cell,'p.id').disabled = dis;
+       findNodeByName(apply_cell,'p.id').checked = up ? true : false;
+
+       var depth_cell = findNodeByName(prow,'pdepth');
+       findNodeByName(depth_cell,'p.depth').disabled = dis;
+       findNodeByName(depth_cell,'p.depth').id = 'perm-depth-' + perm_def.id();
+       selectBuilder(
+               'perm-depth-' + perm_def.id(),
+               globalOrgTypes,
+               (up ? up.depth() : findOrgDepth(user.home_ou())),
+               { label_field           : 'name',
+                 value_field           : 'depth',
+                 empty_label           : '-- Select One --',
+                 empty_value           : '',
+                 clear                 : true }
+       );
+       
+       var grant_cell = findNodeByName(prow,'pgrant');
+       findNodeByName(grant_cell,'p.grantable').disabled = dis;
+       findNodeByName(grant_cell,'p.grantable').checked = up ? (up.grantable() ? true : false) : false;
+
+}
+
 function display_all_addresses () {
        d = document.getElementById('addresses');
        while (d.firstChild)
@@ -507,7 +669,9 @@ function selectBuilder (id, objects, def, args) {
 
        var child_field_name = args['child_field_name'];
 
-       var sel = document.getElementById(id);
+       var sel = id;
+       if (typeof sel != 'object')
+               sel = document.getElementById(sel);
 
        if (args['clear']) {
                for (var o in sel.options) {
@@ -567,3 +731,24 @@ function selectBuilder (id, objects, def, args) {
        }
 }      
 
+function findNodesByClass(root, nodeClass, list) {
+       if(!list) list = [];
+        if( !root || !nodeClass) {
+               return null;
+       }
+        
+        if(root.nodeType != 1) {
+               return null;
+       }
+        
+        if(root.className.match(nodeClass)) list.push( root );
+
+        var children = root.childNodes;
+        
+        for( var i = 0; i != children.length; i++ ) {
+                findNodesByClass(children[i], nodeClass, list);
+        }                       
+                        
+        return list;            
+}                                       
+
index e132867..38ba57e 100644 (file)
                                                display: none;
                        }
 
-                       *[adv='true'] {         visibility: hidden;
-                                       display: none;
-                       }
-
                        table {         border-collapse: collapse;
                                        border: solid black 1px;
                                        margin-bottom: 10px;
@@ -67,7 +63,7 @@
                        <tr>
                                <th colspan="2">User Identifcation</th>
                        </tr>
-                       <tr adv='true'>
+                       <tr class='advanced hideme'>
                                <td class="label">System ID:</td>
                                <td class="value"><input type="text" name="user.id" id="user.id" disabled="true"/></td>
                        </tr>
                                <td class="label">Profile Group:</td>
                                <td class="value"><select name="user.profile" id="user.profile"/></td>
                        </tr>
-                       <tr adv='true'>
-                               <td class="label">Permission Groups:</td>
-                               <td class="value"><select multiple="muliple" name="permgroups" id="permgroups"/></td>
-                       </tr>
                        <tr>
                                <td class="label">Expire Date:</td>
                                <td class="value"><input type="text" name="user.expire_date" id="user.expire_date"/></td>
                        </tr>
-                       <tr>
+                       <tr class='advanced hideme'>
                                <td class="label">Active:</td>
                                <td class="value"><input type="checkbox" name="user.active" id="user.active" value="t"/></td>
                        </tr>
-                       <tr adv='true'>
+                       <tr class='advanced hideme'>
                                <td class="label">Set as Superuser:</td>
                                <td class="value"><input type="checkbox" name="user.super_user" id="user.super_user" value="t"/></td>
                        </tr>
-                       <tr>
+                       <tr class='advanced hideme'>
                                <td class="label">Standing:</td>
                                <td class="value"><select name="user.standing" id="user.standing"/></td>
                        </tr>
                                <td class="label">Set as Family or Group Lead Account:</td>
                                <td class="value"><input type="checkbox" name="user.master_account" id="user.master_account" value="t"/></td>
                        </tr>
-                       <tr>
+                       <tr class='advanced hideme'>
                                <td class="label">"Claims returned" count:</td>
                                <td class="value">
                                        <input type="text" name="user.claims_returned_count" id="user.claims_returned_count" value="0" disabled="true"/>
                        </tr>
 
 
+                       <tr class='advanced hideme'>
+                               <th colspan="2">User Permissions</th>
+                       </tr>
+                       <tr class='advanced hideme'>
+                               <td class="label">Permission Groups:</td>
+                               <td class="value"><select multiple="muliple" name="permgroups" id="permgroups"/></td>
+                       </tr>
+                       <tr class='advanced hideme'>
+                               <td class="label">User Specific Permissions:</td>
+                               <td class="value">
+                                       <table width="100%">
+                                               <thead>
+                                                       <tr>
+                                                               <th>Permission</th>
+                                                               <th>Applied</th>
+                                                               <th>Depth</th>
+                                                               <th>Grantable</th>
+                                                       </tr>
+                                               </thead>
+                                               <tbody id="permissions" name="permissions"/>
+                                       </table>
+                               </td>
+                       </tr>
 
 
                        <tr>
                                </tr>
                        </table>
                </div>
+               <div class='hideme' id="permission-tmpl">
+                       <tr name='prow'>
+                               <td class="label" name='plabel'>
+                                       <span name="p.code"/>
+                               </td>
+                               <td class="value" name='papply'>
+                                       <input type="checkbox" name="p.id" onclick="set_perm(this.parentNode.parentNode);"/>
+                               </td>
+                               <td class="value" name='pdepth'>
+                                       <select onchange="set_perm(this.parentNode.parentNode);" name="p.depth"/>
+                               </td>
+                               <td class="value" name='pgrant'>
+                                       <input type="checkbox" name="p.grantable" onclick="set_perm(this.parentNode.parentNode);"/>
+                               </td>
+                       </tr>
+               </div>
 
                 <div class='hideme' id='survey-tmpl'><div>
 
index 116718b..c323182 100644 (file)
@@ -152,9 +152,10 @@ sub handler {
                                                        $coderef->api_name." : requires ". $coderef->argc
                                        }
                                        if (@args) {
-                                               if (exists $coderef->signature->{params}) {
-                                                       for my $p (0 .. scalar(@{ $coderef->signature->{params} }) - 1 ) {
-                                                               my $s = $coderef->signature->{params}->[$p];
+                                               my $sig = $coderef->signature;
+                                               if ($sig && exists $sig->{params}) {
+                                                       for my $p (0 .. scalar(@{ $sig->{params} }) - 1 ) {
+                                                               my $s = $sig->{params}->[$p];
                                                                my $a = $args[$p];
                                                                if ($s->{class} && JSON->lookup_hint(ref $a) ne $s->{class}) {
                                                                        die "Incorrect param class at position $p : should be a '$$s{class}'";
@@ -230,9 +231,10 @@ sub handler {
                                                                $aref->[2]->api_name." : requires ". $aref->[2]->argc
                                                }
                                                if (@args) {
-                                                       if (exists $aref->[2]->signature->{params}) {
-                                                               for my $p (0 .. scalar(@{ $aref->[2]->signature->{params} }) - 1 ) {
-                                                                       my $s = $aref->[2]->signature->{params}->[$p];
+                                                       my $sig = $aref->[2]->signature;
+                                                       if ($sig && exists $sig->{params}) {
+                                                               for my $p (0 .. scalar(@{ $sig->{params} }) - 1 ) {
+                                                                       my $s = $sig->{params}->[$p];
                                                                        my $a = $args[$p];
                                                                        if ($s->{class} && JSON->lookup_hint(ref $a) ne $s->{class}) {
                                                                                die "Incorrect param class at position $p : should be a '$$s{class}'";