@live-change/session-service 0.1.8 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/authenticator.js CHANGED
@@ -1,32 +1,35 @@
1
1
  const App = require('@live-change/framework')
2
2
  const app = App.app()
3
3
  const definition = require('./definition.js')
4
- const Session = require('./model.js')
4
+ const { Session } = require('./model.js')
5
5
  const { createHmac } = require('crypto')
6
+ const config = definition.config
6
7
 
7
- definition.authenticator(async function(credentials, config) {
8
- const sessionKey = credentials.sessionKey
9
- if(!sessionKey) throw new Error("sessionKey required!")
10
- const sessions = await app.dao.get(
11
- ['database', 'indexRange', app.databaseName, Session.tableName + '_byKey', {
12
- gt: `"${sessionKey}"_`,
13
- lt: `"${sessionKey}"_\xFF`
14
- }])
15
- //console.log("FOUND SESSIONS", sessions)
16
- let session = sessions[0]?.to
17
- if(!session) {
18
- if(config.createSessionOnUpdate) {
19
- session = createHmac('sha256', config.sessionHmacSecret || 'secret')
20
- .update(credentials.sessionKey)
21
- .digest('base64').slice(0, 32)
22
- } else {
23
- const createResult = await app.triggerService(definition.name, {
24
- type: "createSessionKeyIfNotExists",
25
- sessionKey
26
- })
27
- //console.log("CREATE SESSION RESULT", createResult)
28
- session = createResult.session
8
+ definition.authenticator({
9
+ async prepareCredentials(credentials) {
10
+ const sessionKey = credentials.sessionKey
11
+ if(!sessionKey) throw new Error("sessionKey required!")
12
+ const sessions = await app.dao.get(
13
+ ['database', 'indexRange', app.databaseName, Session.tableName + '_byKey', {
14
+ gt: `"${sessionKey}"_`,
15
+ lt: `"${sessionKey}"_\xFF`
16
+ }])
17
+ //console.log("FOUND SESSIONS", sessions)
18
+ let session = sessions[0]?.to
19
+ if(!session) {
20
+ if(config.createSessionOnUpdate) {
21
+ session = createHmac('sha256', config.sessionHmacSecret || 'secret')
22
+ .update(credentials.sessionKey)
23
+ .digest('base64').slice(0, 32)
24
+ } else {
25
+ const createResult = await app.triggerService(definition.name, {
26
+ type: "createSessionKeyIfNotExists",
27
+ sessionKey
28
+ })
29
+ //console.log("CREATE SESSION RESULT", createResult)
30
+ session = createResult.session
31
+ }
29
32
  }
33
+ credentials.session = session
30
34
  }
31
- credentials.session = session
32
35
  })
package/index.js CHANGED
@@ -1,11 +1,7 @@
1
1
  const App = require("@live-change/framework")
2
2
  const app = App.app()
3
3
  const definition = require('./definition.js')
4
- const Session = require('./model.js')
5
-
6
-
7
- const User = definition.foreignModel('user', 'User')
8
-
4
+ const { Session } = require('./model.js')
9
5
 
10
6
  definition.view({
11
7
  name: 'currentSession',
@@ -20,7 +16,6 @@ definition.view({
20
16
  async (input, output, { session, tableName }) => {
21
17
  const mapper = (obj) => (obj || {
22
18
  id: session,
23
- user: null,
24
19
  roles: []
25
20
  })
26
21
  let storedObj = undefined
@@ -81,50 +76,9 @@ definition.trigger({
81
76
  }
82
77
  })
83
78
 
84
- definition.action({
85
- name: "logout",
86
- properties: {
87
- },
88
- async execute({ session }, { client, service }, emit) {
89
- if(!session) session = client.session
90
- if(session != client.session) throw new Error("Wrong session id")
91
- const sessionRow = await Session.get(session)
92
- if(!sessionRow) throw 'notFound'
93
- if(!sessionRow.user) throw "loggedOut"
94
- emit({
95
- type: "loggedOut",
96
- session
97
- })
98
- await service.trigger({
99
- type: "OnLogout",
100
- user: sessionRow.user,
101
- session: client.session
102
- })
103
- return 'loggedOut'
104
- }
105
- })
106
-
107
- definition.trigger({
108
- name: "UserDeleted",
109
- properties: {
110
- user: {
111
- type: User,
112
- idOnly: true
113
- }
114
- },
115
- async execute({ user }, context, emit) {
116
- emit([{
117
- type: "UserDeleted",
118
- user
119
- }])
120
- }
121
- })
122
-
123
-
124
79
  require('./authenticator.js')
125
80
  require('./localIdValidator.js')
126
81
  require('./sessionProperty.js')
127
82
  require('./sessionItem.js')
128
83
 
129
-
130
84
  module.exports = definition
package/model.js CHANGED
@@ -1,29 +1,15 @@
1
1
  const definition = require("./definition.js")
2
2
 
3
- const User = definition.foreignModel('user', 'User')
4
-
5
3
  const Session = definition.model({
6
4
  name: "Session",
7
5
  properties: {
8
6
  key: {
9
7
  type: String
10
- },
11
- user: {
12
- type: User
13
- },
14
- roles: {
15
- type: Array,
16
- of: {
17
- type: String
18
- }
19
8
  }
20
9
  },
21
10
  indexes: {
22
11
  byKey: {
23
12
  property: 'key'
24
- },
25
- byUser: {
26
- property: "user"
27
13
  }
28
14
  }
29
15
  })
@@ -39,115 +25,11 @@ definition.event({
39
25
  }
40
26
  },
41
27
  async execute({ session, key }) {
42
- console.log("SESSION CREATING!", session, "AT", (new Date()).toISOString())
43
28
  await Session.create({
44
29
  id: session,
45
- key: key,
46
- user: null,
47
- roles: []
30
+ key: key
48
31
  })
49
- console.log("SESSION CREATED!", session, "AT", (new Date()).toISOString())
50
- }
51
- })
52
-
53
- definition.event({
54
- name: "loggedIn",
55
- properties: {
56
- session: {
57
- type: Session
58
- },
59
- user: {
60
- type: User
61
- },
62
- roles: {
63
- type: Array,
64
- of: {
65
- type: String
66
- }
67
- },
68
- expire: {
69
- type: Date
70
- }
71
- },
72
- async execute({ session, user, roles, expire, language, timezone }) {
73
- console.log("SESSION UPDATE", session, { user, roles, expire, language, timezone })
74
- await Session.update(session, { user, roles, expire, language, timezone })
75
- }
76
- })
77
-
78
- definition.event({
79
- name: "loggedOut",
80
- properties: {
81
- session: {
82
- type: Session
83
- }
84
- },
85
- async execute({ session }) {
86
- await Session.update(session, [
87
- { op: 'reverseMerge', value: { id: session } },
88
- { op: 'merge', value: { user: null, roles: [] } }
89
- ])
90
- }
91
- })
92
-
93
- definition.event({
94
- name: "UserDeleted",
95
- properties: {
96
- user: {
97
- type: User
98
- }
99
- },
100
- async execute({ user }) {
101
- await app.dao.request(['database', 'query'], app.databaseName, `(${
102
- async (input, output, { table, index, user }) => {
103
- const prefix = `"${user}"_`
104
- await (await input.index(index)).range({
105
- gte: prefix,
106
- lte: prefix+"\xFF\xFF\xFF\xFF"
107
- }).onChange((ind, oldInd) => {
108
- if(ind && ind.to) {
109
- output.table(table).update(ind.to, [
110
- { op: 'reverseMerge', value: { id: ind.to } },
111
- { op: 'merge', value: { user: null, roles: [], expire: null } }
112
- ])
113
- }
114
- })
115
- }
116
- })`, { table: Session.tableName, index: Session.tableName + '_byUser', user })
117
- }
118
- })
119
-
120
- definition.event({
121
- name: "rolesUpdated",
122
- properties: {
123
- user: {
124
- type: User
125
- },
126
- roles: {
127
- type: Array,
128
- of: {
129
- type: String
130
- }
131
- }
132
- },
133
- async execute({ user, roles }) {
134
- await app.dao.request(['database', 'query'], app.databaseName, `(${
135
- async (input, output, { table, index, user, roles }) => {
136
- const prefix = `"${user}"_`
137
- await (await input.index(index)).range({
138
- gte: prefix,
139
- lte: prefix+"\xFF\xFF\xFF\xFF"
140
- }).onChange((ind, oldInd) => {
141
- if(ind && ind.to) {
142
- output.table(table).update(ind.to, [
143
- { op: 'reverseMerge', value: { id: session } },
144
- { op: 'merge', value: { roles } }
145
- ])
146
- }
147
- })
148
- }
149
- })`, { table: Session.tableName, index: Session.tableName + '_byUser', user, roles })
150
32
  }
151
33
  })
152
34
 
153
- module.exports = Session
35
+ module.exports = { Session }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/session-service",
3
- "version": "0.1.8",
3
+ "version": "0.1.13",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -22,6 +22,6 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@live-change/framework": "^0.5.7",
25
- "@live-change/relations-plugin": "^0.1.8"
25
+ "@live-change/relations-plugin": "^0.1.10"
26
26
  }
27
27
  }
package/sessionItem.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const definition = require("./definition.js")
2
2
  const App = require("@live-change/framework")
3
3
  const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
4
- const Session = require("./model.js")
4
+ const { Session } = require("./model.js")
5
5
 
6
6
  definition.processor(function(service, app) {
7
7
 
@@ -22,28 +22,18 @@ definition.processor(function(service, app) {
22
22
  const config = model.sessionItem
23
23
  const writeableProperties = modelProperties || config.writableProperties
24
24
 
25
- console.log("SESSIONM ITEM", model)
25
+ console.log("SESSION ITEM", model)
26
26
 
27
- model.properties.session = new PropertyDefinition({
28
- type: Session,
29
- validation: ['nonEmpty']
30
- })
31
- if(!model.indexes) model.indexes = {}
32
- model.indexes.bySession = new IndexDefinition({
33
- property: 'session'
34
- })
35
- for(const sortField of config.sortBy) {
36
- const sortFieldUc = sortField.slice(0, 1).toUpperCase() + sortField.slice(1)
37
- model.indexes['bySession' + sortFieldUc] = new IndexDefinition({
38
- property: ['session', sortField]
39
- })
27
+ model.itemOf = {
28
+ what: Session,
29
+ ...config
40
30
  }
41
31
 
42
- if(config.readAccess) {
32
+ if(config.sessionReadAccess) {
43
33
  const viewName = 'mySession' + modelName + 's'
44
34
  service.views[viewName] = new ViewDefinition({
45
35
  name: viewName,
46
- access: config.readAccess,
36
+ access: config.sessionReadAccess,
47
37
  properties: App.rangeProperties,
48
38
  daoPath(range, { client, context }) {
49
39
  const path = modelRuntime().indexRangePath('bySession', [client.session], range )
@@ -63,51 +53,13 @@ definition.processor(function(service, app) {
63
53
  })
64
54
  }
65
55
  }
66
- if(config.publicAccess) {
67
- const viewName = 'publicSession' + modelName + 's'
68
- service.views[viewName] = new ViewDefinition({
69
- name: viewName,
70
- access: config.publicAccess,
71
- properties: App.rangeProperties,
72
- daoPath(range, { client, context }) {
73
- return modelRuntime().sortedIndexRangePath('bySession', [range.session], { ...range, session: undefined } )
74
- }
75
- })
76
- for(const sorfField of config.sortBy) {
77
- const sortFieldUc = sorfField.slice(0, 1).toUpperCase() + sortField.slice(1)
78
- const viewName = 'publicSession' + modelName + 'sBy' + sortFieldUc
79
- service.views[viewName] = new ViewDefinition({
80
- name: viewName,
81
- access: config.publicAccess,
82
- properties: App.rangeProperties,
83
- daoPath(range, { client, context }) {
84
- return modelRuntime().sortedIndexRangePath('bySession' + sortFieldUc, [client.session], range )
85
- }
86
- })
87
- }
88
- }
89
56
 
90
- if(config.createAccess || config.writeAccess) {
91
- const eventName = 'session' + modelName + 'Created'
92
- service.events[eventName] = new EventDefinition({
93
- name: eventName,
94
- execute(properties) {
95
- const session = properties.session
96
- const id = properties[modelPropertyName]
97
- let newObject = {}
98
- for(const propertyName of writeableProperties) {
99
- if(properties.hasOwnProperty(propertyName)) {
100
- newObject[propertyName] = properties[propertyName]
101
- }
102
- }
103
- const data = utils.mergeDeep({}, defaults, newObject)
104
- return modelRuntime().create({ ...data, session, id })
105
- }
106
- })
57
+ if(config.sessionCreateAccess || config.sessionWriteAccess) {
58
+ const eventName = 'sessionOwned' + modelName + 'Created'
107
59
  const actionName = 'createMySession' + modelName
108
60
  service.actions[actionName] = new ActionDefinition({
109
61
  name: actionName,
110
- access: config.createAccess || config.writeAccess,
62
+ access: config.sessionCreateAccess || config.sessionWriteAccess,
111
63
  properties: {
112
64
  ...originalModelProperties,
113
65
  [modelPropertyName]: {
@@ -115,35 +67,30 @@ definition.processor(function(service, app) {
115
67
  validation: ['localId']
116
68
  }
117
69
  },
118
- queuedBy: (command) => command.client.session,
70
+ //queuedBy: (command) => command.client.session,
119
71
  waitForEvents: true,
120
72
  async execute(properties, { client, service }, emit) {
121
73
  const id = properties[modelPropertyName] || app.generateUid()
74
+ const entity = await modelRuntime().get(id)
75
+ if(entity) throw 'exists'
122
76
  emit({
123
77
  type: eventName,
124
78
  [modelPropertyName]: id,
125
- session: client.session,
79
+ identifiers: {
80
+ session: client.session,
81
+ },
126
82
  data: properties
127
83
  })
128
84
  return id
129
85
  }
130
86
  })
131
87
  }
132
- if(config.updateAccess || config.writeAccess) {
133
- const eventName = 'session' + modelName + 'Updated'
134
- service.events[eventName] = new EventDefinition({
135
- name: eventName,
136
- execute(properties) {
137
- const data = properties.data
138
- const id = properties[modelPropertyName]
139
- const session = properties.session
140
- return modelRuntime().update(id, { ...data, id, session })
141
- }
142
- })
88
+ if(config.sessionUpdateAccess || config.sessionWriteAccess) {
89
+ const eventName = 'sessionOwned' + modelName + 'Updated'
143
90
  const actionName = 'updateMySession' + modelName
144
91
  service.actions[actionName] = new ActionDefinition({
145
92
  name: actionName,
146
- access: config.updateAccess || config.writeAccess,
93
+ access: config.sessionUpdateAccess || config.sessionWriteAccess,
147
94
  properties: {
148
95
  ...originalModelProperties,
149
96
  [modelPropertyName]: {
@@ -156,8 +103,8 @@ definition.processor(function(service, app) {
156
103
  waitForEvents: true,
157
104
  async execute(properties, { client, service }, emit) {
158
105
  const entity = await modelRuntime().get(properties[modelPropertyName])
159
- if(!entity) throw new Error('not_found')
160
- if(entity.session != client.session) throw new Error('not_authorized')
106
+ if(!entity) throw 'not_found'
107
+ if(entity.session != client.session) throw 'not_authorized'
161
108
  let updateObject = {}
162
109
  for(const propertyName of writeableProperties) {
163
110
  if(properties.hasOwnProperty(propertyName)) {
@@ -165,12 +112,13 @@ definition.processor(function(service, app) {
165
112
  }
166
113
  }
167
114
  const merged = App.utils.mergeDeep({}, entity, updateObject)
168
- console.log("VALIDATE INTERNAL!!!!", merged)
169
115
  await App.validation.validate(merged, validators, { source: action, action, service, app, client })
170
116
  emit({
171
117
  type: eventName,
172
118
  [modelPropertyName]: entity.id,
173
- session: client.session,
119
+ identifiers: {
120
+ session: client.session,
121
+ },
174
122
  data: properties
175
123
  })
176
124
  }
@@ -178,19 +126,12 @@ definition.processor(function(service, app) {
178
126
  const action = service.actions[actionName]
179
127
  const validators = App.validation.getValidators(action, service, action)
180
128
  }
181
- if(config.deleteAccess || config.writeAccess) {
182
- const eventName = 'session' + modelName + 'Deleted'
183
- service.events[eventName] = new EventDefinition({
184
- name: eventName,
185
- execute(properties) {
186
- const id = properties[modelPropertyName]
187
- return modelRuntime().delete(id)
188
- }
189
- })
129
+ if(config.sessionDeleteAccess || config.sessionWriteAccess) {
130
+ const eventName = 'sessionOwned' + modelName + 'Deleted'
190
131
  const actionName = 'deleteMySession' + modelName
191
132
  service.actions[actionName] = new ActionDefinition({
192
133
  name: actionName,
193
- access: config.deleteAccess || config.writeAccess,
134
+ access: config.sessionDeleteAccess || config.sessionWriteAccess,
194
135
  properties: {
195
136
  [modelPropertyName]: {
196
137
  type: model,
@@ -201,12 +142,14 @@ definition.processor(function(service, app) {
201
142
  waitForEvents: true,
202
143
  async execute(properties, { client, service }, emit) {
203
144
  const entity = await modelRuntime().get(properties[modelPropertyName])
204
- if(!entity) throw new Error('not_found')
205
- if(entity.session != client.session) throw new Error('not_authorized')
145
+ if(!entity) throw 'not_found'
146
+ if(entity.session != client.session) throw 'not_authorized'
206
147
  emit({
207
148
  type: eventName,
208
- session: client.session,
209
- [modelPropertyName]: entity.id
149
+ [modelPropertyName]: entity.id,
150
+ identifiers: {
151
+ session: client.session
152
+ }
210
153
  })
211
154
  }
212
155
  })
@@ -1,13 +1,12 @@
1
1
  const definition = require("./definition.js")
2
2
  const App = require("@live-change/framework")
3
3
  const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
4
- const Session = require("./model.js")
4
+ const { Session } = require("./model.js")
5
5
 
6
6
  definition.processor(function(service, app) {
7
7
 
8
8
  for(let modelName in service.models) {
9
9
  const model = service.models[modelName]
10
- console.log("SP", modelName)
11
10
 
12
11
  if(model.sessionProperty) {
13
12
  console.log("MODEL " + modelName + " IS SESSION PROPERTY, CONFIG:", model.sessionProperty)
@@ -16,7 +15,6 @@ definition.processor(function(service, app) {
16
15
  const originalModelProperties = {...model.properties}
17
16
  const modelProperties = Object.keys(model.properties)
18
17
  const defaults = App.utils.generateDefault(model.properties)
19
- const modelPropertyName = modelName.slice(0, 1).toLowerCase() + modelName.slice(1)
20
18
 
21
19
  function modelRuntime() {
22
20
  return service._runtime.models[modelName]
@@ -30,14 +28,6 @@ definition.processor(function(service, app) {
30
28
  ...config
31
29
  }
32
30
 
33
- model.properties.session = new PropertyDefinition({
34
- type: Session,
35
- validation: ['nonEmpty']
36
- })
37
- if(!model.indexes) model.indexes = {}
38
- model.indexes.bySession = new IndexDefinition({
39
- property: 'session'
40
- })
41
31
  if(config.sessionReadAccess) {
42
32
  const viewName = 'mySession' + modelName
43
33
  service.views[viewName] = new ViewDefinition({
@@ -51,18 +41,7 @@ definition.processor(function(service, app) {
51
41
  }
52
42
 
53
43
  if(config.sessionSetAccess || config.sessionWriteAccess) {
54
- const eventName = 'session' + modelName + 'Set'
55
- service.events[eventName] = new EventDefinition({
56
- name: eventName,
57
- properties: {
58
- ...originalModelProperties
59
- },
60
- execute(properties) {
61
- const data = properties.data
62
- const session = properties.session
63
- return modelRuntime().create({...data, session, id: session})
64
- }
65
- })
44
+ const eventName = 'sessionOwned' + modelName + 'Set'
66
45
  const actionName = 'setMySession' + modelName
67
46
  service.actions[actionName] = new ActionDefinition({
68
47
  name: actionName,
@@ -84,7 +63,9 @@ definition.processor(function(service, app) {
84
63
  await App.validation.validate(data, validators, { source: action, action, service, app, client })
85
64
  emit({
86
65
  type: eventName,
87
- session: client.session,
66
+ identifiers: {
67
+ session: client.session
68
+ },
88
69
  data
89
70
  })
90
71
  }
@@ -94,15 +75,7 @@ definition.processor(function(service, app) {
94
75
  }
95
76
 
96
77
  if(config.sessionUpdateAccess || config.sessionWriteAccess) {
97
- const eventName = 'session' + modelName + 'Updated'
98
- service.events[eventName] = new EventDefinition({
99
- name: eventName,
100
- execute(properties) {
101
- const data = properties.data
102
- const session = properties.session
103
- return modelRuntime().update(session, { ...data, session, id: session })
104
- }
105
- })
78
+ const eventName = 'sessionOwned' + modelName + 'Updated'
106
79
  const actionName = 'updateMySession' + modelName
107
80
  service.actions[actionName] = new ActionDefinition({
108
81
  name: actionName,
@@ -115,7 +88,7 @@ definition.processor(function(service, app) {
115
88
  waitForEvents: true,
116
89
  async execute(properties, { client, service }, emit) {
117
90
  const entity = await modelRuntime().get(client.session)
118
- if(!entity) throw new Error('not_found')
91
+ if(!entity) throw 'not_found'
119
92
  let updateObject = {}
120
93
  for(const propertyName of writeableProperties) {
121
94
  if(properties.hasOwnProperty(propertyName)) {
@@ -126,7 +99,9 @@ definition.processor(function(service, app) {
126
99
  await App.validation.validate(merged, validators, { source: action, action, service, app, client })
127
100
  emit({
128
101
  type: eventName,
129
- session: client.session,
102
+ identifiers: {
103
+ session: client.session
104
+ },
130
105
  data: properties || {}
131
106
  })
132
107
  }
@@ -136,13 +111,7 @@ definition.processor(function(service, app) {
136
111
  }
137
112
 
138
113
  if(config.sessionResetAccess || config.sessionWriteAccess) {
139
- const eventName = 'session' + modelName + 'Reset'
140
- service.events[eventName] = new EventDefinition({
141
- name: eventName,
142
- execute({session}) {
143
- return modelRuntime().delete(session)
144
- }
145
- })
114
+ const eventName = 'sessionOwned' + modelName + 'Reset'
146
115
  const actionName = 'resetMySession' + modelName
147
116
  service.actions[actionName] = new ActionDefinition({
148
117
  name: actionName,
@@ -151,10 +120,12 @@ definition.processor(function(service, app) {
151
120
  waitForEvents: true,
152
121
  async execute(properties, {client, service}, emit) {
153
122
  const entity = await modelRuntime().indexObjectGet('bySession', client.session)
154
- if (!entity) throw new Error('not_found')
123
+ if (!entity) throw 'not_found'
155
124
  emit({
156
125
  type: eventName,
157
- session: client.session,
126
+ identifiers: {
127
+ session: client.session
128
+ }
158
129
  })
159
130
  }
160
131
  })