@rpcbase/server 0.84.0 → 0.88.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/database.js +8 -1
- package/mailer/index.js +1 -1
- package/mongoose/index.js +3 -0
- package/package.json +2 -2
- package/queue/dispatch_queue.js +24 -0
- package/{queue.js → queue/index.js} +15 -4
- package/queue/register_queue_listener.js +66 -0
- package/src/auth/index.js +1 -0
- package/src/auth/sign_in.js +1 -0
- package/src/auth/sign_up.js +18 -12
- package/src/models/Invite.js +23 -0
- package/src/models/User.js +17 -0
package/database.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
/* @flow */
|
|
2
|
-
const mongoose = require("mongoose")
|
|
3
2
|
const isPort = require("validator/lib/isPort")
|
|
4
3
|
|
|
4
|
+
const mongoose = require("./mongoose")
|
|
5
|
+
|
|
6
|
+
// load internal models
|
|
7
|
+
require("./src/models/User")
|
|
8
|
+
require("./src/models/Invite")
|
|
9
|
+
require("./src/models/ResetPasswordToken")
|
|
10
|
+
|
|
11
|
+
|
|
5
12
|
const {DATABASE_NAME, DATABASE_PORT, CONTAINER_MODE} = process.env
|
|
6
13
|
|
|
7
14
|
|
package/mailer/index.js
CHANGED
package/mongoose/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpcbase/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.88.0",
|
|
4
4
|
"license": "SSPL-1.0",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"express-session": "1.17.3",
|
|
23
23
|
"glob": "8.0.3",
|
|
24
24
|
"lodash": "4.17.21",
|
|
25
|
-
"mongoose": "6.5.
|
|
25
|
+
"mongoose": "6.5.3",
|
|
26
26
|
"picocolors": "1.0.0",
|
|
27
27
|
"postmark": "3.0.12",
|
|
28
28
|
"redis": "4.2.0",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
const op_names = {
|
|
3
|
+
insert: "create",
|
|
4
|
+
delete: "delete",
|
|
5
|
+
update: "update",
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const dispatch_queue = (queue, model_name, op, doc) => {
|
|
9
|
+
const instance = queue.instance()
|
|
10
|
+
|
|
11
|
+
const tasks = queue.get_tasks()
|
|
12
|
+
|
|
13
|
+
const handler_name = `on_${op_names[op]}_${model_name.toLowerCase()}`
|
|
14
|
+
|
|
15
|
+
// skip if there's no matching handler
|
|
16
|
+
if (!Object.keys(tasks).includes(handler_name)) return
|
|
17
|
+
|
|
18
|
+
// console.log("handler_name", handler_name)
|
|
19
|
+
|
|
20
|
+
queue.add(handler_name, {doc})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
module.exports = dispatch_queue
|
|
@@ -5,16 +5,13 @@ const {WORKER_QUEUE_PORT, CONTAINER_MODE} = process.env
|
|
|
5
5
|
const hostname = CONTAINER_MODE === "native" ? "localhost" : "worker-queue"
|
|
6
6
|
const worker_queue_url = `redis://${hostname}:${WORKER_QUEUE_PORT}`
|
|
7
7
|
|
|
8
|
-
console.log("using worker-queue url", worker_queue_url)
|
|
9
|
-
|
|
10
|
-
|
|
11
8
|
const tasks_list = Object.create(null)
|
|
12
9
|
|
|
13
10
|
let worker_queue
|
|
14
11
|
|
|
15
12
|
const worker_add = async(task_name, payload, options) => {
|
|
16
13
|
const res = await worker_queue.add({task_name, payload}, options)
|
|
17
|
-
//
|
|
14
|
+
// myQueue.add(data, { repeat: { cron: '15 3 * * *' } });
|
|
18
15
|
console.log("created task:", task_name, res.id)
|
|
19
16
|
return res
|
|
20
17
|
}
|
|
@@ -25,7 +22,11 @@ const register_task = (name, fn) => {
|
|
|
25
22
|
tasks_list[name] = fn
|
|
26
23
|
}
|
|
27
24
|
|
|
25
|
+
const get_tasks = () => tasks_list
|
|
26
|
+
|
|
28
27
|
const start_worker = async() => {
|
|
28
|
+
console.log("start worker queue", worker_queue_url)
|
|
29
|
+
|
|
29
30
|
worker_queue = new Queue("worker-queue", worker_queue_url)
|
|
30
31
|
|
|
31
32
|
// error handler
|
|
@@ -55,11 +56,21 @@ const start_worker = async() => {
|
|
|
55
56
|
console.log("ERRRR", err)
|
|
56
57
|
}
|
|
57
58
|
})
|
|
59
|
+
|
|
60
|
+
return worker_queue
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
const get_instance = () => {
|
|
65
|
+
if (!worker_queue) worker_queue = new Queue("worker-queue", worker_queue_url)
|
|
66
|
+
return worker_queue
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
|
|
61
70
|
module.exports = {
|
|
62
71
|
start: start_worker,
|
|
63
72
|
register_task,
|
|
73
|
+
get_tasks,
|
|
64
74
|
add: worker_add,
|
|
75
|
+
instance: get_instance,
|
|
65
76
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
const mongoose = require("../mongoose")
|
|
3
|
+
const queue = require("./index")
|
|
4
|
+
|
|
5
|
+
const dispatch_queue = require("./dispatch_queue")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// Listens for mongodb change events,
|
|
9
|
+
// when a document is created, updated or deleted, dispatch job message
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// mongoose middleware used for delete events
|
|
13
|
+
const mongoose_delete_plugin = (schema) => {
|
|
14
|
+
schema.pre("deleteOne", function(next) {
|
|
15
|
+
throw new Error("rts::deleteOne is deprecated, use findOneAndDelete")
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
// TODO: add other delete operations
|
|
19
|
+
// https://mongoosejs.com/docs/queries.html
|
|
20
|
+
schema.post("findOneAndDelete", function(doc) {
|
|
21
|
+
console.log("queue::findOneAndDelete", "dispatch_doc_change NYI")
|
|
22
|
+
console.log("DEL PLUGIN", doc)
|
|
23
|
+
const model_name = this.model.modelName
|
|
24
|
+
dispatch_queue(queue, model_name, "delete", doc)
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const get_dispatch_change_handler = (model_name) => (change) => {
|
|
30
|
+
const op = change.operationType
|
|
31
|
+
if (["insert", "update"].includes(op)) {
|
|
32
|
+
dispatch_queue(queue, model_name, op, change.fullDocument)
|
|
33
|
+
}
|
|
34
|
+
// else
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const register_queue_listener = async() => {
|
|
39
|
+
// register the mongoose delete plugin
|
|
40
|
+
mongoose.plugin(mongoose_delete_plugin)
|
|
41
|
+
|
|
42
|
+
const models = mongoose.modelNames()
|
|
43
|
+
|
|
44
|
+
models.forEach((model_name) => {
|
|
45
|
+
const model = mongoose.model(model_name)
|
|
46
|
+
|
|
47
|
+
// TODO: implement delete operation fullDocument retrieve,
|
|
48
|
+
// when this is released https://jira.mongodb.org/browse/SERVER-36941
|
|
49
|
+
// this is done via a plugin right now
|
|
50
|
+
const emitter = model.watch({fullDocument: "updateLookup"})
|
|
51
|
+
|
|
52
|
+
emitter.on("change", get_dispatch_change_handler(model_name))
|
|
53
|
+
|
|
54
|
+
emitter.on("error", (err) => {
|
|
55
|
+
console.log("server::queue::register_queue_listener:: change listener emitter got error", err)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
emitter.on("close", () => {
|
|
59
|
+
console.log("queue_listener: emitter closed, model:", model_name)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
module.exports = register_queue_listener
|
package/src/auth/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const reset_password = require("./reset_password")
|
|
|
8
8
|
const set_new_password = require("./set_new_password")
|
|
9
9
|
const check_session = require("./check_session")
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
const sign_up_handler = async(req, res) => {
|
|
12
13
|
const result = await sign_up(req.body, {req})
|
|
13
14
|
res.json(result)
|
package/src/auth/sign_in.js
CHANGED
|
@@ -27,6 +27,7 @@ const sign_in = async({email, password}, ctx) => {
|
|
|
27
27
|
const is_match = await compare_hash(password, hashed_pass)
|
|
28
28
|
|
|
29
29
|
if (is_match) {
|
|
30
|
+
console.log("is match, user signed in wow")
|
|
30
31
|
req.session.user_id = user._id.toString()
|
|
31
32
|
await req.session.save()
|
|
32
33
|
return {
|
package/src/auth/sign_up.js
CHANGED
|
@@ -3,6 +3,8 @@ const {hash_password} = require("@rpcbase/std/crypto/hash")
|
|
|
3
3
|
|
|
4
4
|
const mongoose = require("../../mongoose")
|
|
5
5
|
|
|
6
|
+
const HAS_INVITES = process.env.AUTH_DISABLE_INVITES !== "true"
|
|
7
|
+
|
|
6
8
|
const sign_up = async({email, password}, ctx) => {
|
|
7
9
|
const User = mongoose.model("User")
|
|
8
10
|
const Invite = mongoose.model("Invite")
|
|
@@ -20,18 +22,22 @@ const sign_up = async({email, password}, ctx) => {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
// check if we have an invite for this user
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
if (HAS_INVITES) {
|
|
26
|
+
const invite = await Invite.findOne({email}, null, {ctx})
|
|
27
|
+
|
|
28
|
+
// TODO: mark invite as accepted here
|
|
29
|
+
if (invite && !invite.is_ready) {
|
|
30
|
+
console.log("found an invite, but not ready", email)
|
|
31
|
+
return {
|
|
32
|
+
status: "error",
|
|
33
|
+
message: "Your invite is still pending approval. Expect an email in the next weeks to activate your account."
|
|
34
|
+
}
|
|
35
|
+
} else if (!invite) {
|
|
36
|
+
console.log("no invite for signup email:", email)
|
|
37
|
+
return {
|
|
38
|
+
status: "error",
|
|
39
|
+
message: "No valid invite was found for this email"
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
const mongoose = require("../../mongoose")
|
|
3
|
+
|
|
4
|
+
const Invite = mongoose.model("Invite", {
|
|
5
|
+
email: String,
|
|
6
|
+
email_hash: String, // TODO: unused field?
|
|
7
|
+
token: String,
|
|
8
|
+
expires: Date,
|
|
9
|
+
is_ready: {
|
|
10
|
+
type: Boolean,
|
|
11
|
+
default: false,
|
|
12
|
+
},
|
|
13
|
+
is_sent: {
|
|
14
|
+
type: Boolean,
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
is_accepted: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
module.exports = Invite
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
const mongoose = require("../../mongoose")
|
|
3
|
+
|
|
4
|
+
const User = mongoose.model("User", {
|
|
5
|
+
name: {
|
|
6
|
+
type: String,
|
|
7
|
+
default: "",
|
|
8
|
+
},
|
|
9
|
+
email: String,
|
|
10
|
+
is_email_verified: {
|
|
11
|
+
type: Boolean,
|
|
12
|
+
default: false,
|
|
13
|
+
},
|
|
14
|
+
password_hash: String,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
module.exports = User
|