Use Session class to implement a session cache
[sitka/overdrive-evergreen-opac.git] / src / od_session.coffee
1 # We require the service of a session object to store essentials bits of
2 # information during a login session and between page reloads.  Here, we
3 # define a Session class implementing the service.
4
5 define [
6         'json'
7         'lodash'
8         'od_config'
9 ], (
10         json
11         _
12         config
13 ) ->
14
15         # A base class defining utilitarian methods
16         class U
17                 update: (x) ->
18                         return unless x
19                         t = @
20                         t extends x
21                         return
22                 store: ->
23                         json.stringify @, ( (n, v) -> if n is 'prototype' then undefined else v ), '  '
24                 retrieve: (x) ->
25                         x = if _.isString x
26                                 try
27                                         json.parse x
28                                 catch
29                                         undefined
30
31         class Prefs extends U
32                 @default:
33                         barcode: ''
34                         email_address: ''
35                         home_library: ''
36                 constructor: (x) -> @update x
37                 update: (x) -> super x or Prefs.default
38
39         class Creds extends U
40                 @default:
41                         username: ''
42                         password: 'xxxx'
43                 constructor: (x) -> @update x
44                 update: (x) -> super x or Creds.default
45
46                 # Calculate the effective username: either a barcode or a username (in the
47                 # hope that is a barcode) stored in session cache, or default to a null
48                 # string
49                 un: -> @barcode or @username
50
51                 # Calculate the effective password: either a password stored in session
52                 # cache or a dummy value
53                 pw: (required) -> if required then @password else 'xxxx'
54
55         # An essential role of the session object is to store the properties that
56         # are provided as a result of authenticating the client or the patron.
57         class Token extends U
58                 @default:
59                         access_token: undefined
60                         expires_in: undefined
61                         scope: undefined
62                         token_type: undefined
63
64                 constructor: (x) -> @update x
65                 update: (x) -> super x or Token.default
66                 # Is there a patron access token?  It is enough to test if the
67                 # parameters.scope text string mentions the word 'patron'.
68                 is_patron_access: -> /patron/i.test @scope
69
70         # Store the endpoints of the various APIs.  These include the endpoints for
71         # authenticating the client or the patron and the endpoints for getting
72         # library or patron information.  Upon authentication, other endpoints are
73         # dynamically accumulated within the object.
74         class Links extends U
75                 @default:
76                         token: href:              '//oauth.overdrive.com/token'
77                         libraries: href:            "//api.overdrive.com/v1/libraries/#{config.accountID}"
78                         patrontoken: href: '//oauth-patron.overdrive.com/patrontoken'
79                         patrons: href:       '//patron.api.overdrive.com/v1/patrons/me'
80                         holds: href: ''
81                         checkouts: href: ''
82                         products: ''
83                         advantageAccounts: ''
84                         search: ''
85                         availability: ''
86                 constructor: (x, logged_in) ->
87                         @update x
88                         @calibrate logged_in if x
89                         return
90                 update: (x) ->
91                         if x is undefined
92                                 super Links.default
93                         else
94                                 super x.links if x.links
95                                 super x.linkTemplates if x.linkTemplates
96                         return
97
98                 # Link templates should have empty values unless the current session is
99                 # logged in.
100                 calibrate: (logged_in) ->
101                         @search = @availability = '' unless logged_in
102                         return @
103
104         # Preserve the mapping between format id and format name that will be
105         # provided by the Library Account API.
106         class Labels extends U
107                 constructor: (x) -> @update x
108                 update: (x) -> super @to_object x.formats, 'id', 'name' if x?.formats
109                 # Return a new object from given an object that has a 'key' property and a
110                 # 'value' property
111                 to_object: (from, key, value) ->
112                         to = {}
113                         if from?.length > 0
114                                 to[x[key]] = x[value] for x in from
115                         return to
116
117         # Define a session object as a collection of sub-objects of the types just
118         # defined. Property values of any sub-object can be given in the argument.
119         # The argument can be a JSON string or an object.  If there are no property
120         # values given for a sub-object, intrinsic values will be used.
121         class Session extends U
122                 constructor: (x, logged_in) ->
123                         x = @retrieve x
124                         @prefs = new Prefs  x?.prefs
125                         @creds = new Creds  x?.creds
126                         @token = new Token  x?.token
127                         @links = new Links  x, logged_in
128                         @labels= new Labels x
129                         return
130
131         return Session