Skip to content

Commit 8f07add

Browse files
committed
- support metadata injection.
- remove `id` from `access` function in readSnapshots for multi-snapsthos scenario - support `submit` hook for access checking - support `metadata` called with `commit` hook. - refind document for `access` and `metadata` parameters. - bump version
1 parent b5bc349 commit 8f07add

File tree

8 files changed

+144
-83
lines changed

8 files changed

+144
-83
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Change Logs
22

3+
## v0.0.9
4+
5+
- support metadata injection.
6+
- remove `id` from `access` function in readSnapshots for multi-snapsthos scenario
7+
- support `submit` hook for access checking
8+
- support `metadata` called with `commit` hook.
9+
- refind document for `access` and `metadata` parameters.
10+
11+
312
## v0.0.8
413

514
- support immediately reconnect option

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,49 @@ use `http` and `ws` module to create a WebSocket server ( use `express` as examp
9191
});
9292

9393

94+
### Metadata
95+
96+
If `metadata(opt)` function is provided, it will be called when `commit` hook is triggered with an object including following parameters:
97+
98+
- `m`: the metadata object from sharedb op.
99+
- `type`: either `readSnapshots` or `submit`.
100+
- `collection`: target collection.
101+
- `id`: target doc id. This will be null if there are multiple doc ids - in this case, check `snapshots` instead.
102+
- `req`: the express request object.
103+
- `session`: shorthand for `req.session` from `express-session`.
104+
- `user`: shorthand for `session.user` from `passport`.
105+
106+
edit the `m` field directly to inject necessary metadata. For example, add user id:
107+
108+
metadata = ({m, user, session, collection, id, snaptshos}) -> m.user = (if user? => user.key else 0)
109+
110+
111+
### Access Control
112+
113+
If `access` is function provided, it will be called in following hooks:
114+
115+
- `readSnapshots`
116+
- `submit`
117+
118+
`access(opt)` is called with an object containing following paramters:
119+
120+
- `type`: either `readSnapshots` or `submit`.
121+
- `collection`: target collection.
122+
- `id`: target doc id. This will be null if there are multiple doc ids - in this case, check `snapshots` instead.
123+
- `snapshots`: array of snapshots. Only provided when called by `readSnapshots` hook.
124+
- `req`: the express request object.
125+
- `session`: shorthand for `req.session` from `express-session`.
126+
- `user`: shorthand for `session.user` from `passport`.
127+
128+
`access(opt)` should return a Promise which only resolve when access is granted. By default the returned promise reject a lderror id 1012 error when access is denied.
129+
130+
Here is an example to prevent new document creation:
131+
132+
access = ({snapshots}) ->
133+
if snapshots and !(snapshots.0.id) => return Promise.reject(new Error("") <<< {name: 'lderror', id: 1012});
134+
return Promise.resolve!
135+
136+
94137
## License
95138

96139
MIT

dist/sdb-server.js

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
websocketJsonStream = require('websocket-json-stream');
99
ews = require("./index");
1010
sdbServer = function(opt){
11-
var app, io, session, access, milestoneDb, wss, server, mdb, backend, connect, ret;
12-
app = opt.app, io = opt.io, session = opt.session, access = opt.access, milestoneDb = opt.milestoneDb, wss = opt.wss;
11+
var app, io, session, access, milestoneDb, wss, metadata, server, mdb, backend, connect, ret;
12+
app = opt.app, io = opt.io, session = opt.session, access = opt.access, milestoneDb = opt.milestoneDb, wss = opt.wss, metadata = opt.metadata;
1313
server = null;
1414
mdb = milestoneDb && milestoneDb.enabled ? new sharedbPgMdb({
1515
ioPg: io,
@@ -54,59 +54,67 @@
5454
return cb();
5555
}
5656
session = req.session;
57-
user = session && session.passport && session.passport.user;
57+
user = (session && session.passport && session.passport.user) || {};
5858
ref$ = agent.custom;
5959
ref$.req = req;
6060
ref$.session = session;
6161
ref$.user = user;
6262
return cb();
6363
});
64-
backend.use('readSnapshots', function(arg$, cb){
65-
var collection, snapshots, agent, ref$, req, session, user, id;
66-
collection = arg$.collection, snapshots = arg$.snapshots, agent = arg$.agent;
67-
if (!agent.stream.ws) {
64+
if (metadata != null) {
65+
backend.use('commit', function(arg$, cb){
66+
var collection, agent, snapshot, op, id, ref$, req, session, user;
67+
collection = arg$.collection, agent = arg$.agent, snapshot = arg$.snapshot, op = arg$.op, id = arg$.id;
68+
if (!agent.stream.ws) {
69+
return cb();
70+
}
71+
ref$ = agent.custom, req = ref$.req, session = ref$.session, user = ref$.user;
72+
metadata(import$({
73+
m: op.m
74+
}, agent.custom));
6875
return cb();
69-
}
70-
ref$ = agent.custom, req = ref$.req, session = ref$.session, user = ref$.user;
71-
id = (snapshots[0] || {}).id;
72-
return (access != null
73-
? access({
74-
user: user,
75-
session: session,
76-
collection: collection,
76+
});
77+
}
78+
if (access != null) {
79+
backend.use('readSnapshots', function(arg$, cb){
80+
var agent, collection, snapshots, id;
81+
agent = arg$.agent, collection = arg$.collection, snapshots = arg$.snapshots;
82+
if (!agent.stream.ws) {
83+
return cb();
84+
}
85+
id = snapshots.length > 1
86+
? null
87+
: snapshots[0].id;
88+
return access(import$({
7789
id: id,
90+
collection: collection,
7891
snapshots: snapshots,
7992
type: 'readSnapshots'
80-
})
81-
: Promise.resolve()).then(function(){
82-
return cb();
83-
})['catch'](function(e){
84-
var ref$;
85-
return cb(e || (ref$ = new Error(), ref$.name = 'lderror', ref$.id = 1012, ref$));
93+
}, agent.custom)).then(function(){
94+
return cb();
95+
})['catch'](function(e){
96+
var ref$;
97+
return cb(e || (ref$ = new Error(), ref$.name = 'lderror', ref$.id = 1012, ref$));
98+
});
8699
});
87-
});
88-
backend.use('reply', function(arg$, cb){
89-
var collection, agent, reply, ref$, req, session, user, act, id;
90-
collection = arg$.collection, agent = arg$.agent, reply = arg$.reply;
91-
if (!agent.stream.ws) {
92-
return cb();
93-
}
94-
ref$ = agent.custom, req = ref$.req, session = ref$.session, user = ref$.user;
95-
act = reply.a;
96-
id = reply.d;
97-
return cb();
98-
});
99-
backend.use('receive', function(arg$, cb){
100-
var collection, agent, data, ref$, req, session, user, act, id;
101-
collection = arg$.collection, agent = arg$.agent, data = arg$.data;
102-
if (!agent.stream.ws) {
103-
return cb();
104-
}
105-
ref$ = agent.custom, req = ref$.req, session = ref$.session, user = ref$.user;
106-
act = data.a;
107-
id = data.d;
108-
return cb();
109-
});
100+
backend.use('submit', function(arg$, cb){
101+
var collection, agent, id;
102+
collection = arg$.collection, agent = arg$.agent, id = arg$.id;
103+
if (!agent.stream.ws) {
104+
return cb();
105+
}
106+
return access(import$({
107+
id: id,
108+
collection: collection,
109+
type: 'submit'
110+
}, agent.custom)).then(function(){
111+
return cb();
112+
})['catch'](function(e){
113+
var ref$;
114+
return cb(e || (ref$ = new Error(), ref$.name = 'lderror', ref$.id = 1012, ref$));
115+
});
116+
});
117+
}
110118
return ret = {
111119
server: server,
112120
sdb: backend,
@@ -115,4 +123,9 @@
115123
};
116124
};
117125
module.exports = sdbServer;
126+
function import$(obj, src){
127+
var own = {}.hasOwnProperty;
128+
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
129+
return obj;
130+
}
118131
}).call(this);

dist/sdb-server.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@plotdb/ews",
3-
"version": "0.0.8",
3+
"version": "0.0.9",
44
"description": "elastic websocket",
55
"main": "dist/index.min.js",
66
"browser": "dist/index.min.js",

src/sdb-server.ls

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ require! <[sharedb @plotdb/sharedb-postgres sharedb-pg-mdb ws http websocket-jso
22
ews = require "./index"
33

44
sdb-server = (opt) ->
5-
{app, io, session, access, milestone-db, wss} = opt
5+
{app, io, session, access, milestone-db, wss, metadata} = opt
66

77
server = null
88
mdb = if (milestone-db and milestone-db.enabled) =>
@@ -59,40 +59,33 @@ sdb-server = (opt) ->
5959
backend.use \connect, ({agent, req, stream}, cb) ->
6060
if !req or !stream.ws => return cb!
6161
session = req.session
62-
user = session and session.passport and session.passport.user
62+
user = (session and session.passport and session.passport.user) or {}
6363
agent.custom <<< {req, session, user}
6464
cb!
6565

66-
# 4. Backend handle readSnapshot request
67-
# Decide if an user can get access to certain doc.
68-
backend.use \readSnapshots, ({collection, snapshots, agent}, cb) ->
69-
# no websocket - it's server stream
70-
if !agent.stream.ws => return cb!
71-
{req, session, user} = agent.custom
72-
id = (snapshots.0 or {}).id
73-
(if access? => access({user, session, collection, id, snapshots, type: \readSnapshots}) else Promise.resolve!)
74-
.then -> cb!
75-
.catch (e) -> cb(e or (new Error! <<< {name: \lderror, id: 1012}))
66+
# 4.a Backend handle metadata request
67+
if metadata? =>
68+
backend.use \commit, ({collection, agent, snapshot, op, id}, cb) ->
69+
if !agent.stream.ws => return cb!
70+
{req, session, user} = agent.custom
71+
metadata({m: op.m} <<< agent.custom)
72+
cb!
7673

77-
# access control in both reply and receive middleware
78-
backend.use \reply, ({collection, agent, reply}, cb) ->
79-
if !agent.stream.ws => return cb!
80-
{req, session, user} = agent.custom
81-
act = reply.a
82-
id = reply.d
83-
cb!
84-
#(if act != \hs and access? => access({user, session, collection, id, type: \reply}) else Promise.resolve!)
85-
# .then -> cb!
86-
# .catch (e) -> cb(e or (new Error! <<< {name: \lderror, id: 1012}))
87-
backend.use \receive, ({collection, agent, data}, cb) ->
88-
if !agent.stream.ws => return cb!
89-
{req, session, user} = agent.custom
90-
act = data.a
91-
id = data.d
92-
cb!
93-
#(if act != \hs and access? => access({user, session, collection, id, data, type: \receive}) else Promise.resolve!)
94-
# .then -> cb!
95-
# .catch -> cb(e or (new Error! <<< {name: \lderror, id: 1012}))
74+
# 4.b Backend handle readSnapshot request
75+
# Decide if an user can get access to certain doc.
76+
if access? =>
77+
backend.use \readSnapshots, ({agent, collection, snapshots}, cb) ->
78+
# no websocket - it's server stream
79+
if !agent.stream.ws => return cb!
80+
id = if snapshots.length > 1 => null else snapshots.0.id
81+
access({id, collection, snapshots, type: \readSnapshots} <<< agent.custom)
82+
.then -> cb!
83+
.catch (e) -> cb(e or (new Error! <<< {name: \lderror, id: 1012}))
84+
backend.use \submit, ({collection, agent, id}, cb) ->
85+
if !agent.stream.ws => return cb!
86+
access({id, collection, type: \submit} <<< agent.custom)
87+
.then -> cb!
88+
.catch (e) -> cb(e or (new Error! <<< {name: \lderror, id: 1012}))
9689

9790
ret = { server, sdb: backend, connect, wss }
9891

web/server.ls

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ root = path.join(path.dirname(fs.realpathSync __filename.replace(/\(js\)$/,'')),
88
config = do
99
pg: do
1010
uri: "postgres://grantdash:pg@#{process.env.DB_HOST or \localhost}/pg"
11-
database: "xinmeti"
12-
user: "xinmeti"
13-
password: "itemnix"
11+
database: "pg"
12+
user: "pg"
13+
password: "pg"
1414
host: "#{process.env.DB_HOST or \localhost}"
15-
port: "#{process.env.DB_PORT or 5432}"
15+
port: "#{process.env.DB_PORT or 15432}"
1616

1717
server = do
1818
init: ->
@@ -21,7 +21,10 @@ server = do
2121

2222
server = http.create-server app
2323
wss = new ws.Server { server: server }
24-
{sdb,connect} = sharedb-wrapper {app, io: config.pg, wss}
24+
25+
access = ({user, session}) -> Promise.resolve!
26+
metadata = ({m, user, session}) -> m.user = 1
27+
{sdb,connect} = sharedb-wrapper {app, io: config.pg, wss, access, metadata}
2528

2629
wss.on \connection, (ws, req) ->
2730
myws = new ews {ws}

0 commit comments

Comments
 (0)