@rpcbase/server 0.209.0 → 0.210.0

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/bin.js CHANGED
@@ -9,11 +9,25 @@ const {hideBin} = require("yargs/helpers")
9
9
  const pack = require("./package.json")
10
10
  const start_server_infrastructure = require("./cli/start_server_infrastructure")
11
11
  const build_server = require("./cli/build_server")
12
+ const check_args = require("./cli/check_args")
12
13
  const run_agent = require("./cli/run_agent")
13
14
 
14
15
  let is_command = false
15
16
 
16
17
  const args = yargs(hideBin(process.argv))
18
+ .option("verbose", {
19
+ type: "boolean",
20
+ default: false,
21
+ description: "Run with verbose logging"
22
+ })
23
+ .option("sessions", {
24
+ type: "boolean",
25
+ default: false,
26
+ description: "Run with the sessions store enabled"
27
+ })
28
+ .option("session", {
29
+ hidden: true,
30
+ })
17
31
  .command("start", "runs server/infrastructure", () => {}, (args) => {
18
32
  is_command = true
19
33
  start_server_infrastructure(args)
@@ -26,19 +40,19 @@ const args = yargs(hideBin(process.argv))
26
40
  is_command = true
27
41
  build_server()
28
42
  })
29
- .option("verbose", {
30
- type: "boolean",
31
- default: false,
32
- description: "Run with verbose logging"
33
- })
43
+ .check(check_args)
34
44
  .parse()
35
45
 
46
+
36
47
  if (!is_command) {
37
- console.log("server default com22mand")
48
+ console.log("server default command exiting.")
49
+ process.exit(0)
38
50
  }
39
51
 
40
52
 
41
53
  // TODO: why was this needed
54
+ // -> was this for when running in docker ? I think yes
55
+
42
56
  // // add helpers to ensure proper process termination
43
57
  // const exit_clean = () => {
44
58
  // process.exit()
package/boot/index.js CHANGED
@@ -1,3 +1,27 @@
1
1
  /* @flow */
2
-
3
2
  require("./setup_env")
3
+ //
4
+ const http = require("http")
5
+
6
+ const {rpc_router, client_router, express, database} = require("../")
7
+ const mongoose = require("../mongoose")
8
+ //
9
+ require("@rpcbase/access-control")(mongoose)
10
+ const realtime_state = require("../rts")
11
+
12
+ const {SERVER_PORT} = process.env
13
+
14
+ const app = express()
15
+ const server = http.createServer(app)
16
+
17
+
18
+ realtime_state(server)
19
+
20
+
21
+
22
+ server.listen(SERVER_PORT, "0.0.0.0", () => {
23
+ console.log(`listening on 0.0.0.0:${SERVER_PORT}`)
24
+ })
25
+
26
+
27
+ module.exports = app
@@ -0,0 +1,17 @@
1
+ /* @flow */
2
+
3
+ const check_args = (args) => {
4
+ if (typeof args.session !== "undefined") {
5
+ throw new Error("Did you mean --sessions?")
6
+ }
7
+
8
+ const raw_args = JSON.parse(process.env.npm_config_argv).original
9
+ if (raw_args.indexOf("--no-session") > -1) {
10
+ throw new Error("Did you mean --no-sessions?")
11
+ }
12
+
13
+ return true
14
+ }
15
+
16
+
17
+ module.exports = check_args
package/cli/run_docker.js CHANGED
@@ -5,7 +5,7 @@ const fs = require("fs")
5
5
 
6
6
  const is_production = "yes" === process.env.INFRASTRUCTURE_IS_PRODUCTION
7
7
 
8
- const run_docker = async(infrastructure_dir, proj_prefix) => {
8
+ const run_docker = async(infrastructure_dir, proj_prefix, args) => {
9
9
  // env
10
10
  const env_path = path.relative(infrastructure_dir, path.join(process.cwd(), "./.env"))
11
11
  const base_env_path = path.relative(infrastructure_dir, path.join(process.cwd(), "./.env.base"))
@@ -34,9 +34,21 @@ const run_docker = async(infrastructure_dir, proj_prefix) => {
34
34
 
35
35
  console.log(cmd_args.join(" "))
36
36
 
37
+ const ps_env = {
38
+ ...process.env,
39
+ }
40
+
41
+ if (args.sessions) {
42
+ ps_env.RB_SESSION_STORE = "yes"
43
+ }
44
+
37
45
  // WARNING: blocks the process
38
46
  // this is the only way to have docker-compose shut down gracefully
39
- execSync(`${cmd} ${cmd_args.join(" ")}`, {cwd: infrastructure_dir, stdio: "inherit"})
47
+ execSync(`${cmd} ${cmd_args.join(" ")}`, {
48
+ cwd: infrastructure_dir,
49
+ stdio: "inherit",
50
+ env: ps_env
51
+ })
40
52
 
41
53
  }
42
54
 
package/cli/run_native.js CHANGED
@@ -167,9 +167,19 @@ const run_native = (infrastructure_dir, proj_prefix, args) => {
167
167
 
168
168
  const processes = get_processes(args)
169
169
 
170
+
170
171
  const run_process = (item) => {
171
- // console.log("run_native:run_process:item", item)
172
- const ps = spawn(item.cmd[0], item.cmd[1], {env: {...process.env, CONTAINER_MODE: "native"}})
172
+ const ps_env = {
173
+ ...process.env,
174
+ CONTAINER_MODE: "native",
175
+ }
176
+
177
+ if (args.sessions) {
178
+ ps_env.RB_SESSION_STORE = "yes"
179
+ }
180
+
181
+
182
+ const ps = spawn(item.cmd[0], item.cmd[1], {env: ps_env})
173
183
 
174
184
  // TODO: add flag to force print
175
185
  if (!NO_PRINT_LIST.includes(item.name)) {
package/express/index.js CHANGED
@@ -7,9 +7,9 @@ const request_ip = require("request-ip")
7
7
 
8
8
  // functionality middlewares
9
9
  const auth = require("../src/auth")
10
+ const sessions = require("../src/sessions")
10
11
 
11
12
  const dev_save_coverage = require("./dev_save_coverage")
12
- const session_middleware = require("./session_middleware")
13
13
 
14
14
 
15
15
  const log = debug("rb:server")
@@ -90,7 +90,8 @@ module.exports = () => {
90
90
  credentials: true // IMPORTANT: required to enable set-cookie
91
91
  }))
92
92
 
93
- app.use(session_middleware)
93
+
94
+ sessions(app)
94
95
 
95
96
  app.get("/__/ping", (req, res) => res.json({message: "pong"}))
96
97
  app.post("/__/ping", (req, res) => res.json({message: "pong"}))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/server",
3
- "version": "0.209.0",
3
+ "version": "0.210.0",
4
4
  "license": "SSPL-1.0",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -10,6 +10,7 @@
10
10
  "test": "echo \"Error: no test specified\" && exit 0"
11
11
  },
12
12
  "dependencies": {
13
+ "@rpcbase/access-control": "0.25.0",
13
14
  "@rpcbase/agent": "0.30.0",
14
15
  "@rpcbase/std": "0.6.0",
15
16
  "bluebird": "3.7.2",
package/rts/index.js CHANGED
@@ -8,6 +8,9 @@ const sift = require("sift")
8
8
  const debug = require("debug")
9
9
  const colors = require("picocolors")
10
10
 
11
+ const mongoose = require("../mongoose")
12
+
13
+
11
14
  const log = debug("rb:rts:server")
12
15
 
13
16
  const is_production = process.env.IS_PRODUCTION === "yes"
@@ -360,65 +363,72 @@ const disconnect_handler = (socket_id, reason) => {
360
363
  }
361
364
 
362
365
 
363
- const rts_server = (mongoose, session_middleware) => {
364
-
366
+ const rts_server = (server) => {
365
367
  // register the delete plugin
366
368
  mongoose.plugin(mongoose_delete_plugin)
367
369
  // txn plugin
368
370
  mongoose.plugin(mongoose_txn_plugin)
369
371
 
372
+ //
373
+ const io = new Server(server, {
374
+ transports: is_production ? ["websocket", "polling"] : ["websocket"],
375
+ allowUpgrades: true,
376
+ cors: {
377
+ // TODO: dynamic client ports
378
+ // TODO: check if is production
379
+ origin: `http://localhost:${process.env.CLIENT_PORT}`,
380
+ methods: ["GET", "POST"],
381
+ credentials: true,
382
+ },
383
+ })
370
384
 
371
- return async(server) => {
372
- //
373
- const io = new Server(server, {
374
- transports: is_production ? ["websocket", "polling"] : ["websocket"],
375
- allowUpgrades: true,
376
- cors: {
377
- // TODO: dynamic client ports
378
- // TODO: check if is production
379
- origin: `http://localhost:${process.env.CLIENT_PORT}`,
380
- methods: ["GET", "POST"],
381
- credentials: true,
382
- },
383
- })
385
+ //
386
+ const has_session_store = process.env.RB_SESSION_STORE === "yes"
384
387
 
388
+ if (has_session_store) {
389
+ const session_store_middleware = require("../src/sessions/session_store_middleware")
385
390
  // socket io session middleware
386
391
  io.use((socket, next) => {
387
- session_middleware(socket.request, {}, next)
392
+ session_store_middleware(socket.request, {}, next)
388
393
  })
394
+ } else {
395
+ const session_proxy_middleware = require("../src/sessions/session_proxy_middleware")
396
+ // proxy middleware that checks the rb-tenant-id header
397
+ io.use((socket, next) => {
398
+ session_proxy_middleware(socket.request, {}, next)
399
+ })
400
+ }
389
401
 
390
- // WARNING: TODO: socket session tmp disabled
391
- // io.on('connection', (socket) => {
392
- // const session = socket.request.session;
393
- // session.connections++;
394
- // session.save();
395
- // });
396
-
397
- io.on("connection", (socket) => {
398
- _sockets[socket.id] = socket
399
- console.log("socket connected", socket.id)
400
- //
401
- socket.on("register_query", (payload) => {
402
- add_change_stream(mongoose, socket.id, payload)
403
- })
402
+ // io.on('connection', (socket) => {
403
+ // const session = socket.request.session;
404
+ // session.connections++;
405
+ // session.save();
406
+ // });
404
407
 
405
- socket.on("remove_query", (payload) => {
406
- remove_query(socket.id, payload)
407
- })
408
+ io.on("connection", (socket) => {
409
+ _sockets[socket.id] = socket
410
+ console.log("socket connected", socket.id)
411
+ //
412
+ socket.on("register_query", (payload) => {
413
+ add_change_stream(mongoose, socket.id, payload)
414
+ })
408
415
 
409
- socket.on("run_query", (payload) => {
410
- try {
411
- run_query(mongoose, socket.id, payload)
412
- } catch (err) {
413
- console.log("run_query caught error", err)
414
- }
415
- })
416
+ socket.on("remove_query", (payload) => {
417
+ remove_query(socket.id, payload)
418
+ })
416
419
 
417
- socket.on("disconnect", (reason) => {
418
- disconnect_handler(socket.id, reason)
419
- })
420
+ socket.on("run_query", (payload) => {
421
+ try {
422
+ run_query(mongoose, socket.id, payload)
423
+ } catch (err) {
424
+ console.log("run_query caught error", err)
425
+ }
420
426
  })
421
- }
427
+
428
+ socket.on("disconnect", (reason) => {
429
+ disconnect_handler(socket.id, reason)
430
+ })
431
+ })
422
432
  }
423
433
 
424
434
 
@@ -3,10 +3,13 @@ const debug = require("debug")
3
3
 
4
4
  const User = require("../models/User")
5
5
 
6
- const log = debug("rb:auth:check_session")
6
+ const log = debug("rb:auth")
7
7
  log.useColors = true
8
8
 
9
9
 
10
+ const has_session_store = process.env.RB_SESSION_STORE === "yes"
11
+
12
+ // TODO: we must separate the check session from the check user exists
10
13
  const check_session = async(payload, ctx) => {
11
14
  const {req} = ctx
12
15
 
@@ -25,7 +28,7 @@ const check_session = async(payload, ctx) => {
25
28
  }
26
29
  if (!user) {
27
30
  is_signed_in = false
28
- req.session.destroy(/* TODO: this should take callback */)
31
+ req.session.destroy?.(/* TODO: this should take callback */)
29
32
  }
30
33
 
31
34
  // TODO: check if user is disabled or blocked
package/src/auth/index.js CHANGED
@@ -10,32 +10,32 @@ const check_session = require("./check_session")
10
10
 
11
11
 
12
12
  const sign_up_handler = async(req, res) => {
13
- const result = await sign_up(req.body, {req})
13
+ const result = await sign_up(req.body, {req, res})
14
14
  res.json(result)
15
15
  }
16
16
 
17
17
  const sign_in_handler = async(req, res) => {
18
- const result = await sign_in(req.body, {req})
18
+ const result = await sign_in(req.body, {req, res})
19
19
  res.json(result)
20
20
  }
21
21
 
22
22
  const sign_out_handler = async(req, res) => {
23
- const result = await sign_out(req.body, {req})
23
+ const result = await sign_out(req.body, {req, res})
24
24
  res.json(result)
25
25
  }
26
26
 
27
27
  const reset_password_handler = async(req, res) => {
28
- const result = await reset_password(req.body, {req})
28
+ const result = await reset_password(req.body, {req, res})
29
29
  res.json(result)
30
30
  }
31
31
 
32
32
  const set_new_password_handler = async(req, res) => {
33
- const result = await set_new_password(req.body, {req})
33
+ const result = await set_new_password(req.body, {req, res})
34
34
  res.json(result)
35
35
  }
36
36
 
37
37
  const check_session_handler = async(req, res) => {
38
- const result = await check_session(req.body, {req})
38
+ const result = await check_session(req.body, {req, res})
39
39
  res.json(result)
40
40
  }
41
41
 
@@ -4,8 +4,13 @@ const debug = require("debug")
4
4
 
5
5
  const mongoose = require("../../mongoose")
6
6
 
7
+
7
8
  const log = debug("rb:auth:signin")
8
9
 
10
+ const has_session_store = process.env.RB_SESSION_STORE === "yes"
11
+
12
+ const USER_ID_HEADER = "rb-user-id"
13
+
9
14
  const fail = () => ({
10
15
  errors: {form: "Invalid email or password"}
11
16
  })
@@ -13,7 +18,7 @@ const fail = () => ({
13
18
  const sign_in = async({email, password}, ctx) => {
14
19
  const User = mongoose.model("User")
15
20
 
16
- const {req} = ctx
21
+ const {req, res} = ctx
17
22
 
18
23
  // find matching user
19
24
  const user = await User.findOne({email}, null)
@@ -29,14 +34,14 @@ const sign_in = async({email, password}, ctx) => {
29
34
  if (is_match) {
30
35
  log("compare_hash is match")
31
36
  const user_id = user._id.toString()
32
- req.session.user_id = user_id
33
- // add email to an array so that in the future
34
- // we can support multiple accounts on the same session
35
- if (!req.session.user_emails) {
36
- req.session.user_emails = []
37
+
38
+ if (has_session_store) {
39
+ req.session.user_id = user_id
40
+ await req.session.save()
41
+ } else {
42
+ // On sign in success, we set this header to tell the reverse-proxy sign in was OK
43
+ res.setHeader(USER_ID_HEADER, user_id)
37
44
  }
38
- req.session.user_emails.push(email)
39
- await req.session.save()
40
45
 
41
46
  log("session saved, user is signed in")
42
47
 
@@ -30,8 +30,9 @@ const rpc_router = (app) => {
30
30
  app.post(`/rpc/${route_path}`, async_wrapper(async(req, res) => {
31
31
 
32
32
  console.log(`POST /rpc/${route_path}`)
33
+
33
34
  // TODO: add jaegerclient / opentelemetry
34
- const result = await rpc_fn(req.body, {req})
35
+ const result = await rpc_fn(req.body, {req, res})
35
36
  res.json(result)
36
37
  }))
37
38
  })
@@ -0,0 +1,26 @@
1
+ /* @flow */
2
+ const is_development = process.env.NODE_ENV === "development"
3
+
4
+ module.exports = (app) => {
5
+ const has_session_store = process.env.RB_SESSION_STORE === "yes"
6
+
7
+ if (has_session_store) {
8
+ console.log("using session store")
9
+
10
+ const session_store_middleware = require("./session_store_middleware")
11
+ app.use(session_store_middleware)
12
+ } else {
13
+ console.log("using reverse-proxy sessions")
14
+
15
+ // warn the user
16
+ if (is_development) {
17
+ app.use(require("./warning_proxy_middleware"))
18
+ }
19
+
20
+
21
+
22
+ const session_proxy_middleware = require("./session_proxy_middleware")
23
+ app.use(session_proxy_middleware)
24
+ }
25
+
26
+ }
@@ -0,0 +1,18 @@
1
+ /* @flow */
2
+
3
+ const USER_ID_HEADER = "rb-user-id"
4
+
5
+ // Production middleware used to retrieve session from the proxy
6
+ const session_proxy_middleware = (req, res, next) => {
7
+ req.session = {}
8
+
9
+ const user_id = req.headers[USER_ID_HEADER]
10
+ if (user_id) {
11
+ req.session.user_id = user_id
12
+ }
13
+
14
+ next()
15
+ }
16
+
17
+
18
+ module.exports = session_proxy_middleware
@@ -62,9 +62,8 @@ setTimeout(async() => {
62
62
  store: new redis_store({client: redis_client}),
63
63
  proxy: true,
64
64
  saveUninitialized: false,
65
- // WARNING
66
- // TODO: use session secret from env
67
- secret: "session secret wowow",
65
+ // WARNING DO NOT USE IN PROD
66
+ secret: "not so secret",
68
67
  resave: false,
69
68
  cookie: {
70
69
  // TODO: set to secure in production
@@ -0,0 +1,16 @@
1
+ /* @flow */
2
+
3
+
4
+ const warning_proxy_middleware = (req, res, next) => {
5
+ const {host} = req.headers
6
+
7
+ if (host.startsWith("localhost:")) {
8
+ res.status(500)
9
+ res.json({status: "error", message: "are you running with the proxy address ? you shouldn't be using localhost when you are running the app with the reverse proxyy"})
10
+ return
11
+ } else {
12
+ next()
13
+ }
14
+ }
15
+
16
+ module.exports = warning_proxy_middleware