@live-change/session-service 0.1.10 → 0.2.1

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.10",
3
+ "version": "0.2.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -8,13 +8,13 @@
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/live-change/session-service.git"
11
+ "url": "git+https://github.com/live-change/live-change-services.git"
12
12
  },
13
13
  "license": "MIT",
14
14
  "bugs": {
15
- "url": "https://github.com/live-change/session-service/issues"
15
+ "url": "https://github.com/live-change/live-change-services/issues"
16
16
  },
17
- "homepage": "https://github.com/live-change/session-service",
17
+ "homepage": "https://github.com/live-change/live-change-services",
18
18
  "author": {
19
19
  "email": "michal@laszczewski.pl",
20
20
  "name": "Michał Łaszczewski",
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@live-change/framework": "^0.5.7",
25
- "@live-change/relations-plugin": "^0.1.9"
26
- }
25
+ "@live-change/relations-plugin": "^0.1.10"
26
+ },
27
+ "gitHead": "e7b365e7bcc4512d9922d9fbe5eb21ed1b418c63"
27
28
  }
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
 
@@ -24,7 +24,7 @@ definition.processor(function(service, app) {
24
24
 
25
25
  console.log("SESSION ITEM", model)
26
26
 
27
- model.propertyOf = {
27
+ model.itemOf = {
28
28
  what: Session,
29
29
  ...config
30
30
  }
@@ -33,7 +33,7 @@ definition.processor(function(service, app) {
33
33
  const viewName = 'mySession' + modelName + 's'
34
34
  service.views[viewName] = new ViewDefinition({
35
35
  name: viewName,
36
- access: config.readAccess,
36
+ access: config.sessionReadAccess,
37
37
  properties: App.rangeProperties,
38
38
  daoPath(range, { client, context }) {
39
39
  const path = modelRuntime().indexRangePath('bySession', [client.session], range )
@@ -55,26 +55,11 @@ definition.processor(function(service, app) {
55
55
  }
56
56
 
57
57
  if(config.sessionCreateAccess || config.sessionWriteAccess) {
58
- const eventName = 'session' + modelName + 'Created'
59
- service.events[eventName] = new EventDefinition({
60
- name: eventName,
61
- execute(properties) {
62
- const session = properties.session
63
- const id = properties[modelPropertyName]
64
- let newObject = {}
65
- for(const propertyName of writeableProperties) {
66
- if(properties.hasOwnProperty(propertyName)) {
67
- newObject[propertyName] = properties[propertyName]
68
- }
69
- }
70
- const data = utils.mergeDeep({}, defaults, newObject)
71
- return modelRuntime().create({ ...data, session, id })
72
- }
73
- })
58
+ const eventName = 'sessionOwned' + modelName + 'Created'
74
59
  const actionName = 'createMySession' + modelName
75
60
  service.actions[actionName] = new ActionDefinition({
76
61
  name: actionName,
77
- access: config.createAccess || config.writeAccess,
62
+ access: config.sessionCreateAccess || config.sessionWriteAccess,
78
63
  properties: {
79
64
  ...originalModelProperties,
80
65
  [modelPropertyName]: {
@@ -82,14 +67,18 @@ definition.processor(function(service, app) {
82
67
  validation: ['localId']
83
68
  }
84
69
  },
85
- queuedBy: (command) => command.client.session,
70
+ //queuedBy: (command) => command.client.session,
86
71
  waitForEvents: true,
87
72
  async execute(properties, { client, service }, emit) {
88
73
  const id = properties[modelPropertyName] || app.generateUid()
74
+ const entity = await modelRuntime().get(id)
75
+ if(entity) throw 'exists'
89
76
  emit({
90
77
  type: eventName,
91
78
  [modelPropertyName]: id,
92
- session: client.session,
79
+ identifiers: {
80
+ session: client.session,
81
+ },
93
82
  data: properties
94
83
  })
95
84
  return id
@@ -97,20 +86,11 @@ definition.processor(function(service, app) {
97
86
  })
98
87
  }
99
88
  if(config.sessionUpdateAccess || config.sessionWriteAccess) {
100
- const eventName = 'session' + modelName + 'Updated'
101
- service.events[eventName] = new EventDefinition({
102
- name: eventName,
103
- execute(properties) {
104
- const data = properties.data
105
- const id = properties[modelPropertyName]
106
- const session = properties.session
107
- return modelRuntime().update(id, { ...data, id, session })
108
- }
109
- })
89
+ const eventName = 'sessionOwned' + modelName + 'Updated'
110
90
  const actionName = 'updateMySession' + modelName
111
91
  service.actions[actionName] = new ActionDefinition({
112
92
  name: actionName,
113
- access: config.updateAccess || config.writeAccess,
93
+ access: config.sessionUpdateAccess || config.sessionWriteAccess,
114
94
  properties: {
115
95
  ...originalModelProperties,
116
96
  [modelPropertyName]: {
@@ -123,8 +103,8 @@ definition.processor(function(service, app) {
123
103
  waitForEvents: true,
124
104
  async execute(properties, { client, service }, emit) {
125
105
  const entity = await modelRuntime().get(properties[modelPropertyName])
126
- if(!entity) throw new Error('not_found')
127
- 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'
128
108
  let updateObject = {}
129
109
  for(const propertyName of writeableProperties) {
130
110
  if(properties.hasOwnProperty(propertyName)) {
@@ -132,12 +112,13 @@ definition.processor(function(service, app) {
132
112
  }
133
113
  }
134
114
  const merged = App.utils.mergeDeep({}, entity, updateObject)
135
- console.log("VALIDATE INTERNAL!!!!", merged)
136
115
  await App.validation.validate(merged, validators, { source: action, action, service, app, client })
137
116
  emit({
138
117
  type: eventName,
139
118
  [modelPropertyName]: entity.id,
140
- session: client.session,
119
+ identifiers: {
120
+ session: client.session,
121
+ },
141
122
  data: properties
142
123
  })
143
124
  }
@@ -145,19 +126,12 @@ definition.processor(function(service, app) {
145
126
  const action = service.actions[actionName]
146
127
  const validators = App.validation.getValidators(action, service, action)
147
128
  }
148
- if(config.deleteAccess || config.writeAccess) {
149
- const eventName = 'session' + modelName + 'Deleted'
150
- service.events[eventName] = new EventDefinition({
151
- name: eventName,
152
- execute(properties) {
153
- const id = properties[modelPropertyName]
154
- return modelRuntime().delete(id)
155
- }
156
- })
129
+ if(config.sessionDeleteAccess || config.sessionWriteAccess) {
130
+ const eventName = 'sessionOwned' + modelName + 'Deleted'
157
131
  const actionName = 'deleteMySession' + modelName
158
132
  service.actions[actionName] = new ActionDefinition({
159
133
  name: actionName,
160
- access: config.deleteAccess || config.writeAccess,
134
+ access: config.sessionDeleteAccess || config.sessionWriteAccess,
161
135
  properties: {
162
136
  [modelPropertyName]: {
163
137
  type: model,
@@ -168,12 +142,14 @@ definition.processor(function(service, app) {
168
142
  waitForEvents: true,
169
143
  async execute(properties, { client, service }, emit) {
170
144
  const entity = await modelRuntime().get(properties[modelPropertyName])
171
- if(!entity) throw new Error('not_found')
172
- 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'
173
147
  emit({
174
148
  type: eventName,
175
- session: client.session,
176
- [modelPropertyName]: entity.id
149
+ [modelPropertyName]: entity.id,
150
+ identifiers: {
151
+ session: client.session
152
+ }
177
153
  })
178
154
  }
179
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({
@@ -98,7 +88,7 @@ definition.processor(function(service, app) {
98
88
  waitForEvents: true,
99
89
  async execute(properties, { client, service }, emit) {
100
90
  const entity = await modelRuntime().get(client.session)
101
- if(!entity) throw new Error('not_found')
91
+ if(!entity) throw 'not_found'
102
92
  let updateObject = {}
103
93
  for(const propertyName of writeableProperties) {
104
94
  if(properties.hasOwnProperty(propertyName)) {
@@ -130,7 +120,7 @@ definition.processor(function(service, app) {
130
120
  waitForEvents: true,
131
121
  async execute(properties, {client, service}, emit) {
132
122
  const entity = await modelRuntime().indexObjectGet('bySession', client.session)
133
- if (!entity) throw new Error('not_found')
123
+ if (!entity) throw 'not_found'
134
124
  emit({
135
125
  type: eventName,
136
126
  identifiers: {