Galen Charlton
2017 Evergreen International Conference
First substantial commit on 4 February 2005
commit 940e152e588a9b1c1b4f18cbbecf46691cb2f58c
Author: phasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Date:   Fri Feb 4 22:08:15 2005 +0000
    Initial revision
    
    
    git-svn-id: svn://svn.open-ils.org/ILS/trunk@2 dcc99617-32d9-48b4-a31d-7c20da2025e4
| Year | Commits | 
|---|---|
| 2005 | 2,562 | 
| 2006 | 4,115 | 
| 2007 | 1,142 | 
| 2008-2013 | 12,553 | 
| 2014 | 708 | 
| 2015 | 928 | 
| 2016 | 897 | 
| 2017 | 421 | 
Particularly if you're a cat who cannot be trusted with a mouse
Cats on a Farm by davidmaitland on Flickr CC-BY
CREATE TABLE container.user_bucket (
    id  SERIAL  PRIMARY KEY,
    owner   INT NOT NULL
            REFERENCES actor.usr (id)
                ON DELETE CASCADE
                ON UPDATE CASCADE
                DEFERRABLE
                INITIALLY DEFERRED,
    name    TEXT    NOT NULL,
    btype   TEXT    NOT NULL DEFAULT 'misc' REFERENCES container.user_bucket_type (code) DEFERRABLE INITIALLY DEFERRED,
    description TEXT,
    pub BOOL    NOT NULL DEFAULT FALSE,
    create_time TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT NOW(),
    CONSTRAINT ub_name_once_per_owner UNIQUE (owner,name,btype)
);
CREATE TABLE container.user_bucket_item (
    id      SERIAL  PRIMARY KEY,
    bucket      INT NOT NULL
                REFERENCES container.user_bucket (id)
                    ON DELETE CASCADE
                    ON UPDATE CASCADE
                    DEFERRABLE
                    INITIALLY DEFERRED,
    target_user INT NOT NULL
                REFERENCES actor.usr (id)
                    ON DELETE CASCADE
                    ON UPDATE CASCADE
                    DEFERRABLE
                    INITIALLY DEFERRED,
    pos         INT,
    create_time TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT NOW()
);           code           |            label            
--------------------------+-----------------------------
 misc                     | Miscellaneous
 folks                    | Friends
 folks:pub_book_bags.view | List Published Book Lists
 folks:pub_book_bags.add  | Add to Published Book Lists
 folks:circ.view          | View Circulations
 folks:circ.renew         | Renew Circulations
 folks:circ.checkout      | Checkout Items
 folks:hold.view          | View Holds
 folks:hold.cancel        | Cancel HoldsA bucket of type "folks" stores a user's friends
id          | 3
owner       | 236
name        | folks
btype       | folks
description | 
pub         | f
create_time | 2017-04-01 20:35:14.013986+00id          | 3
bucket      | 3
target_user | 237
pos         | 
create_time | 2017-04-01 20:35:46.26597+00Each entry in a bucket is a friend
But friendship counts only if it's mutual!
It's not enough to be friendly... specific permissions must be delegated. This is done usingthe other "folks:" bucket types.
id          | 2
owner       | 236
name        | folks:hold.view
btype       | folks:hold.view
description | 
pub         | f
create_time | 2017-04-01 20:28:32.672987+00Permission delegation does NOT need to be mutual
// here be Freddie, operating srfsh
srfsh# request open-ils.actor open-ils.actor.friends.perms.apply \
       "cd365b8ca54495c900dd0a851ccb8cff" 236, 237, "hold.view"
Received Data: "1"
// and here I am later, checking on his hold request
srfsh# request open-ils.circ open-ils.circ.holds.retrieve \
       "9eb6c9709849ce2a85bb678c64c77449", 236                                                                   
Received Data: [
  { 
    "__c":"ahr",
    "__p":[
      null,
      null,
      null,
      null,
      "f",
      null,
      null,
      null,
      null,
      "T",
      null,
      263,Expand the permission delegation mostly entails adding some calls to  OpenILS::Application::Actor::Friends->friend_perm_allowed()
	Queries are stored in the query schema as structures that can be turned into SQL SELECT (and UNION, INTERSECT, and EXCEPT) statements
query.stored_query
query.from_relation
-[ RECORD 1 ]-+-------
id            | 26
type          | SELECT
use_all       | f
use_distinct  | f
from_clause   | 11
where_clause  | 
having_clause | 
limit_count   | 
offset_count  | -[ RECORD 1 ]---+------------------------------------
id              | 11
type            | RELATION
table_name      | reporter.materialized_simple_record
class_name      | 
subquery        | 
function_call   | 
table_alias     | rmsr
parent_relation | 
seq_no          | 1
join_type       | 
on_clause       | 
-[ RECORD 1 ]---+---------
id              | 11
type            | RELATION
table_name      | 
class_name      | rmsr
subquery        | 
function_call   | 
table_alias     | 
parent_relation | 
seq_no          | 1
join_type       | 
on_clause       | 
or
query.expr_xcol
query.select_item
-[ RECORD 1 ]+-------
id           | 61
parenthesize | f
parent_expr  | 
seq_no       | 1
table_alias  | rmsr
column_name  | title
negate       | f
-[ RECORD 2 ]+-------
id           | 62
parenthesize | f
parent_expr  | 
seq_no       | 1
table_alias  | rmsr
column_name  | author
negate       | f-[ RECORD 1 ]+---
id           | 48
stored_query | 26
seq_no       | 1
expression   | 61
column_alias | 
grouped_by   | f
-[ RECORD 2 ]+---
id           | 50
stored_query | 26
seq_no       | 2
expression   | 62
column_alias | 
grouped_by   | fsrfsh# open open-ils.qstore                                               
Service open-ils.qstore opened
srfsh# request open-ils.qstore open-ils.qstore.prepare 26                 
Received Data: {
  "token":"5_1491150953_5837",
  "bind_variables":{
    
  }
}
------------------------------------
Request Completed Successfully
Request Time in seconds: 0.006293
------------------------------------
srfsh# request open-ils.qstore open-ils.qstore.columns "5_1491150953_5837" 
Received Data: [
  "title",
  "author"
]
srfsh# request open-ils.qstore open-ils.qstore.sql "5_1491150953_5837"    
// turned the "\n" into literal newlines for this slide
Received Data: "SELECT
   \"rmsr\".title,
   \"rmsr\".author 
FROM
   reporter.materialized_simple_record AS \"rmsr\";
"srfsh# request open-ils.qstore open-ils.qstore.execute "5_1491150953_5837"
Received Data: [
  "la canzone italiana del novecento",
  "baldazzi, gianfranco"
]
Received Data: [
  "le concerto",
  "ferchault, guy"
]
Received Data: [
  "piano concertos nos 2, 3 & 4",
  "kabalevsky, dmitry borisovich"
]
Received Data: [
  "huntington student recital, dec 6 1999",
  null
]opensrf@dev-galen:~$ /home/gmc/OpenSRF/src/python/srfsh.py
Loading module oils.srfsh...OK.
srfsh# idl show class acp
Loading and parsing IDL...OK
------------------------------------------------------------
Item [acp] asset.copy
------------------------------------------------------------
[0]  age_protect [link @crahp]
[1]  alert_message [text]
[2]  barcode [text]
[3]  call_number [link @acn]
[4]  circ_as_type [text]
[5]  circ_lib [org_unit]
[6]  circ_modifier [link @ccm]
[7]  circulate [bool]
[8]  copy_number [text]
[9]  create_date [timestamp]
[10] active_date [timestamp]
[11] creator [link @au]srfsh# router service-stats
Received Data: {
    "open-ils.circ":161,
    "open-ils.qstore":10,
    "open-ils.cat":0,
    "open-ils.actor":11,
    "open-ils.trigger":0,
    "open-ils.permacrud":0,
    "open-ils.auth":2,
    "open-ils.auth_proxy":0,
    "open-ils.url_verify":0,
    "open-ils.supercat":26,
    "open-ils.collections":0,
    "open-ils.storage":2,
    "open-ils.pcrud":0,
    "open-ils.vandelay":0,
    "opensrf.dbmath":0,<?xml version="1.0"?>
<!-- This file follows the standard bootstrap config file layout found in opensrf_core.xml -->
<srfsh>
  <router_name>router</router_name>
  <domain>private.localhost</domain>
  <username>opensrf</username>
  <passwd>IAmTheVeryModelOfAModernMajorPassword</passwd>
  <port>5222</port>
  <logfile>/openils/var/log/srfsh.log</logfile>
  <loglevel>4</loglevel>
  <client>true</client>
  <plugins>
    <plugin module="oils.srfsh"/>
  </plugins>
</srfshdef handle_org_setting(srfsh, args):
    ''' Retrieves the requested org setting.
    Arguments:
        org unit id,
        org setting name
    '''
    org_unit = args[0]
    setting = args[1]
    srfsh.handle_request([
        'open-ils.actor', 
        'open-ils.actor.ou_setting.ancestor_default', 
        org_unit, 
        ',"%s"' % setting
    ])
# ...
srfsh.add_command(command = 'org_setting', handler = handle_org_setting)