@prosopo/database 2.5.3 → 2.6.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/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # @prosopo/database
2
+
3
+ ## 2.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 52feffc: Adjustable difficulty img captcha
8
+ - Updated dependencies [52feffc]
9
+ - @prosopo/types-database@2.6.1
10
+ - @prosopo/types@2.6.1
11
+ - @prosopo/user-access-policy@2.6.1
12
+
13
+ ## 2.6.0
14
+
15
+ ### Minor Changes
16
+
17
+ - a0bfc8a: bump all pkg versions since independent versioning applied
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [a0bfc8a]
22
+ - @prosopo/config@2.6.0
23
+ - @prosopo/common@2.6.0
24
+ - @prosopo/types@2.6.0
25
+ - @prosopo/types-database@2.6.0
26
+ - @prosopo/user-access-policy@2.6.0
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const mongo = require("./mongo.cjs");
4
+ const mongoMemory = require("./mongoMemory.cjs");
5
+ exports.MongoDatabase = mongo.MongoDatabase;
6
+ exports.MongoMemoryDatabase = mongoMemory.MongoMemoryDatabase;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const common = require("@prosopo/common");
4
+ const mongodb = require("mongodb");
5
+ const mongoose = require("mongoose");
6
+ mongoose.set("strictQuery", false);
7
+ const DEFAULT_ENDPOINT = "mongodb://127.0.0.1:27017";
8
+ class MongoDatabase {
9
+ constructor(url, dbname, authSource, logger) {
10
+ this.connected = false;
11
+ const baseEndpoint = url || DEFAULT_ENDPOINT;
12
+ const parsedUrl = new URL(baseEndpoint);
13
+ if (dbname) {
14
+ parsedUrl.pathname = dbname;
15
+ }
16
+ if (authSource) {
17
+ parsedUrl.searchParams.set("authSource", authSource);
18
+ }
19
+ this._url = parsedUrl.toString();
20
+ this.safeURL = this.url.replace(/\w+:\w+/, "<Credentials>");
21
+ this.dbname = dbname || parsedUrl.pathname.replace("/", "");
22
+ this.logger = logger || common.getLoggerDefault();
23
+ }
24
+ get url() {
25
+ return this._url;
26
+ }
27
+ getConnection() {
28
+ if (!this.connection) {
29
+ throw new common.ProsopoDBError("DATABASE.CONNECTION_UNDEFINED", {
30
+ context: { failedFuncName: this.getConnection.name },
31
+ logger: this.logger
32
+ });
33
+ }
34
+ return this.connection;
35
+ }
36
+ /**
37
+ * @description Connect to the database and set the various tables
38
+ */
39
+ async connect() {
40
+ this.logger.info(`Mongo url: ${this.safeURL}`);
41
+ try {
42
+ if (this.connected) {
43
+ this.logger.info(`Database connection to ${this.safeURL} already open`);
44
+ return;
45
+ }
46
+ this.connection = await new Promise((resolve, reject) => {
47
+ const connection = mongoose.createConnection(this.url, {
48
+ dbName: this.dbname,
49
+ serverApi: mongodb.ServerApiVersion.v1
50
+ });
51
+ connection.on("open", () => {
52
+ this.logger.info(`Database connection to ${this.safeURL} opened`);
53
+ this.connected = true;
54
+ resolve(connection);
55
+ });
56
+ connection.on("error", (err) => {
57
+ this.connected = false;
58
+ this.logger.error(`Database error: ${err}`);
59
+ reject(err);
60
+ });
61
+ connection.on("connected", () => {
62
+ this.logger.info(`Database connected to ${this.safeURL}`);
63
+ this.connected = true;
64
+ resolve(connection);
65
+ });
66
+ connection.on("disconnected", () => {
67
+ this.connected = false;
68
+ this.logger.info(`Database disconnected from ${this.safeURL}`);
69
+ });
70
+ connection.on("reconnected", () => {
71
+ this.logger.info(`Database reconnected to ${this.safeURL}`);
72
+ this.connected = true;
73
+ resolve(connection);
74
+ });
75
+ connection.on("reconnectFailed", () => {
76
+ this.connected = false;
77
+ this.logger.error(`Database reconnect failed to ${this.safeURL}`);
78
+ });
79
+ connection.on("close", () => {
80
+ this.connected = false;
81
+ this.logger.info(`Database connection to ${this.safeURL} closed`);
82
+ });
83
+ connection.on("fullsetup", () => {
84
+ this.connected = true;
85
+ this.logger.info(
86
+ `Database connection to ${this.safeURL} is fully setup`
87
+ );
88
+ resolve(connection);
89
+ });
90
+ });
91
+ } catch (e) {
92
+ this.logger.error(`Database connection error: ${e}`);
93
+ throw e;
94
+ }
95
+ }
96
+ /** Close connection to the database */
97
+ async close() {
98
+ this.logger.debug(`Closing connection to ${this.safeURL}`);
99
+ await this.connection?.close();
100
+ }
101
+ }
102
+ exports.MongoDatabase = MongoDatabase;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const mongodbMemoryServer = require("mongodb-memory-server");
4
+ const mongo = require("./mongo.cjs");
5
+ class MongoMemoryDatabase extends mongo.MongoDatabase {
6
+ constructor(url, dbname, logger, authSource) {
7
+ const mongod = new mongodbMemoryServer.MongoMemoryServer();
8
+ const mongoMemoryURL = mongod.getUri();
9
+ super(mongoMemoryURL, dbname, authSource, logger);
10
+ this.running = false;
11
+ this.mongod = mongod;
12
+ this._url = mongoMemoryURL;
13
+ }
14
+ connect() {
15
+ if (!this.running) {
16
+ this.mongod?.start();
17
+ this.running = true;
18
+ } else {
19
+ }
20
+ return super.connect();
21
+ }
22
+ async close() {
23
+ await super.close();
24
+ await this.mongod?.stop();
25
+ this.running = false;
26
+ }
27
+ }
28
+ exports.MongoMemoryDatabase = MongoMemoryDatabase;
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const common = require("@prosopo/common");
4
+ const typesDatabase = require("@prosopo/types-database");
5
+ require("../base/index.cjs");
6
+ const mongo = require("../base/mongo.cjs");
7
+ const logger = common.getLoggerDefault();
8
+ var TableNames = /* @__PURE__ */ ((TableNames2) => {
9
+ TableNames2["frictionlessToken"] = "frictionlessToken";
10
+ TableNames2["session"] = "session";
11
+ TableNames2["commitment"] = "commitment";
12
+ TableNames2["powcaptcha"] = "powcaptcha";
13
+ return TableNames2;
14
+ })(TableNames || {});
15
+ const CAPTCHA_TABLES = [
16
+ {
17
+ collectionName: "session",
18
+ modelName: "Session",
19
+ schema: typesDatabase.StoredSessionRecordSchema
20
+ },
21
+ {
22
+ collectionName: "powcaptcha",
23
+ modelName: "PowCaptcha",
24
+ schema: typesDatabase.StoredPoWCaptchaRecordSchema
25
+ },
26
+ {
27
+ collectionName: "commitment",
28
+ modelName: "UserCommitment",
29
+ schema: typesDatabase.StoredUserCommitmentRecordSchema
30
+ }
31
+ ];
32
+ class CaptchaDatabase extends mongo.MongoDatabase {
33
+ constructor(url, dbname, authSource, logger2) {
34
+ super(url, dbname, authSource, logger2);
35
+ this.tables = {};
36
+ }
37
+ async connect() {
38
+ await super.connect();
39
+ CAPTCHA_TABLES.map(({ collectionName, modelName, schema }) => {
40
+ if (this.connection) {
41
+ this.tables[collectionName] = this.connection.model(modelName, schema);
42
+ }
43
+ });
44
+ }
45
+ getTables() {
46
+ if (!this.tables) {
47
+ throw new common.ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
48
+ context: { failedFuncName: this.getTables.name },
49
+ logger: this.logger
50
+ });
51
+ }
52
+ return this.tables;
53
+ }
54
+ async saveCaptchas(sessionEvents, imageCaptchaEvents, powCaptchaEvents) {
55
+ await this.connect();
56
+ if (sessionEvents.length) {
57
+ const result = await this.tables.session.bulkWrite(
58
+ sessionEvents.map((document) => {
59
+ const { _id, ...safeDoc } = document;
60
+ return {
61
+ insertOne: {
62
+ document: safeDoc
63
+ }
64
+ };
65
+ })
66
+ );
67
+ logger.info("Mongo Saved Session Events", result.insertedCount);
68
+ }
69
+ if (imageCaptchaEvents.length) {
70
+ const result = await this.tables.commitment.bulkWrite(
71
+ imageCaptchaEvents.map((doc) => {
72
+ const { _id, ...safeDoc } = doc;
73
+ return {
74
+ updateOne: {
75
+ filter: { id: safeDoc.id },
76
+ update: { $set: safeDoc },
77
+ upsert: true
78
+ }
79
+ };
80
+ })
81
+ );
82
+ logger.info("Mongo Saved Image Events", result.upsertedCount);
83
+ }
84
+ if (powCaptchaEvents.length) {
85
+ const result = await this.tables.powcaptcha.bulkWrite(
86
+ powCaptchaEvents.map((doc) => {
87
+ const { _id, ...safeDoc } = doc;
88
+ return {
89
+ updateOne: {
90
+ filter: { challenge: safeDoc.challenge },
91
+ update: { $set: safeDoc },
92
+ upsert: true
93
+ }
94
+ };
95
+ })
96
+ );
97
+ logger.info("Mongo Saved PoW Events", result.upsertedCount);
98
+ }
99
+ await this.close();
100
+ }
101
+ async getCaptchas(filter = {}, limit = 100) {
102
+ await this.connect();
103
+ try {
104
+ const commitmentResults = await this.tables.commitment.find(filter).limit(limit).lean();
105
+ const powCaptchaResults = await this.tables.powcaptcha.find(filter).limit(limit).lean();
106
+ return {
107
+ userCommitmentRecords: commitmentResults,
108
+ powCaptchaRecords: powCaptchaResults
109
+ };
110
+ } catch (error) {
111
+ throw new common.ProsopoDBError("DATABASE.QUERY_ERROR", {
112
+ context: {
113
+ error,
114
+ filter,
115
+ limit,
116
+ failedFuncName: this.getCaptchas.name
117
+ },
118
+ logger: this.logger
119
+ });
120
+ } finally {
121
+ await this.close();
122
+ }
123
+ }
124
+ }
125
+ exports.CaptchaDatabase = CaptchaDatabase;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const common = require("@prosopo/common");
4
+ const typesDatabase = require("@prosopo/types-database");
5
+ require("../base/index.cjs");
6
+ const mongo = require("../base/mongo.cjs");
7
+ const CLIENT_TABLES = [
8
+ {
9
+ collectionName: typesDatabase.TableNames.accounts,
10
+ modelName: "Account",
11
+ schema: typesDatabase.AccountSchema
12
+ }
13
+ ];
14
+ class ClientDatabase extends mongo.MongoDatabase {
15
+ constructor(url, dbname, authSource, logger) {
16
+ super(url, dbname, authSource, logger);
17
+ this.tables = {};
18
+ }
19
+ async connect() {
20
+ await super.connect();
21
+ CLIENT_TABLES.map(({ collectionName, modelName, schema }) => {
22
+ if (this.connection) {
23
+ this.tables[collectionName] = this.connection.model(modelName, schema);
24
+ }
25
+ });
26
+ }
27
+ getTables() {
28
+ if (!this.tables) {
29
+ throw new common.ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
30
+ context: { failedFuncName: this.getTables.name },
31
+ logger: this.logger
32
+ });
33
+ }
34
+ return this.tables;
35
+ }
36
+ async getUpdatedClients(updatedAtTimestamp) {
37
+ await this.connect();
38
+ const newClientRecords = await this.tables.accounts.find(
39
+ {
40
+ $or: [
41
+ { "sites.updatedAt": { $gt: updatedAtTimestamp } },
42
+ { "sites.updatedAt": { $exists: false } }
43
+ ],
44
+ "users.status": "active"
45
+ },
46
+ { "sites.siteKey": 1, "sites.settings": 1, "sites.tier": 1 }
47
+ ).lean().then(
48
+ (records) => records.map(
49
+ (record) => ({
50
+ account: record.sites.siteKey,
51
+ // Rename "sites.siteKey" to "account"
52
+ settings: record.sites.settings,
53
+ // Rename "sites.settings" to "settings"
54
+ tier: record.tier
55
+ // Keep "tier" as is
56
+ })
57
+ )
58
+ );
59
+ await this.close();
60
+ return newClientRecords;
61
+ }
62
+ }
63
+ exports.ClientDatabase = ClientDatabase;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const types = require("@prosopo/types");
4
+ const mongo = require("../base/mongo.cjs");
5
+ const mongoMemory = require("../base/mongoMemory.cjs");
6
+ const captcha = require("./captcha.cjs");
7
+ const client = require("./client.cjs");
8
+ const provider = require("./provider.cjs");
9
+ const Databases = {
10
+ [types.DatabaseTypes.Values.mongo]: mongo.MongoDatabase,
11
+ [types.DatabaseTypes.Values.provider]: provider.ProviderDatabase,
12
+ [types.DatabaseTypes.Values.client]: client.ClientDatabase,
13
+ [types.DatabaseTypes.Values.captcha]: captcha.CaptchaDatabase,
14
+ [types.DatabaseTypes.Values.mongoMemory]: mongoMemory.MongoMemoryDatabase
15
+ };
16
+ exports.CaptchaDatabase = captcha.CaptchaDatabase;
17
+ exports.ClientDatabase = client.ClientDatabase;
18
+ exports.ProviderDatabase = provider.ProviderDatabase;
19
+ exports.Databases = Databases;