UNPKG

@wepublish/api-db-mongodb

Version:

We.publish Database adapter for mongoDB

389 lines 15.2 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MongoDBUserAdapter = void 0; const bcrypt_1 = __importDefault(require("bcrypt")); const api_1 = require("@wepublish/api"); const mongodb_1 = require("mongodb"); const schema_1 = require("./schema"); const utility_1 = require("../utility"); const defaults_1 = require("./defaults"); const cursor_1 = require("./cursor"); class MongoDBUserAdapter { constructor(db, bcryptHashCostFactor, locale) { this.users = db.collection(schema_1.CollectionName.Users); this.bcryptHashCostFactor = bcryptHashCostFactor; this.locale = locale; } async createUser({ input, password }) { try { const passwordHash = await bcrypt_1.default.hash(password, this.bcryptHashCostFactor); const { insertedId: id } = await this.users.insertOne({ createdAt: new Date(), modifiedAt: new Date(), email: input.email, emailVerifiedAt: null, oauth2Accounts: [], name: input.name, firstName: input.firstName, preferredName: input.preferredName, address: input.address, active: input.active, lastLogin: null, properties: input.properties, roleIDs: input.roleIDs, password: passwordHash, paymentProviderCustomers: input.paymentProviderCustomers || [] }); return this.getUserByID(id); } catch (err) { if (err instanceof mongodb_1.MongoError && err.code === utility_1.MongoErrorCode.DuplicateKey) { throw new Error('Email address already exists!'); } throw err; } } async getUser(email) { const user = await this.users.findOne({ email }); if (user) { return { id: user._id, createdAt: user.createdAt, modifiedAt: user.modifiedAt, email: user.email, emailVerifiedAt: user.emailVerifiedAt, oauth2Accounts: user.oauth2Accounts, name: user.name, firstName: user.firstName, preferredName: user.preferredName, address: user.address, active: user.active, lastLogin: user.lastLogin, properties: user.properties, roleIDs: user.roleIDs, paymentProviderCustomers: user.paymentProviderCustomers }; } else { return null; } } async updateUser({ id, input }) { const { value } = await this.users.findOneAndUpdate({ _id: id }, { $set: { modifiedAt: new Date(), name: input.name, firstName: input.firstName, preferredName: input.preferredName, address: input.address, active: input.active, properties: input.properties, email: input.email, emailVerifiedAt: input.emailVerifiedAt, roleIDs: input.roleIDs } }, { returnOriginal: false }); if (!value) return null; const { _id: outID } = value; return this.getUserByID(outID); } async deleteUser({ id }) { const { deletedCount } = await this.users.deleteOne({ _id: id }); return deletedCount !== 0 ? id : null; } async resetUserPassword({ id, password }) { const { value } = await this.users.findOneAndUpdate({ _id: id }, { $set: { modifiedAt: new Date(), password: await bcrypt_1.default.hash(password, this.bcryptHashCostFactor) } }, { returnOriginal: false }); if (!value) return null; const { _id: outID } = value; return this.getUserByID(outID); } async getUsersByID(ids) { const users = await this.users.find({ _id: { $in: ids } }).toArray(); return users.map(user => { return { id: user._id, createdAt: user.createdAt, modifiedAt: user.modifiedAt, email: user.email, emailVerifiedAt: user.emailVerifiedAt, oauth2Accounts: user.oauth2Accounts, name: user.name, firstName: user.firstName, preferredName: user.preferredName, address: user.address, active: user.active, lastLogin: user.lastLogin, properties: user.properties, roleIDs: user.roleIDs, paymentProviderCustomers: user.paymentProviderCustomers }; }); } async getUserForCredentials({ email, password }) { const user = await this.users.findOne({ email }); if (user && (await bcrypt_1.default.compare(password, user.password))) { return { id: user._id, createdAt: user.createdAt, modifiedAt: user.modifiedAt, email: user.email, emailVerifiedAt: user.emailVerifiedAt, oauth2Accounts: user.oauth2Accounts, name: user.name, firstName: user.firstName, preferredName: user.preferredName, address: user.address, active: user.active, lastLogin: user.lastLogin, properties: user.properties, roleIDs: user.roleIDs, paymentProviderCustomers: user.paymentProviderCustomers }; } return null; } async getUserByID(id) { const user = await this.users.findOne({ _id: id }); if (user) { return { id: user._id, createdAt: user.createdAt, modifiedAt: user.modifiedAt, email: user.email, emailVerifiedAt: user.emailVerifiedAt, oauth2Accounts: user.oauth2Accounts, name: user.name, firstName: user.firstName, preferredName: user.preferredName, address: user.address, active: user.active, lastLogin: user.lastLogin, properties: user.properties, roleIDs: user.roleIDs, paymentProviderCustomers: user.paymentProviderCustomers }; } else { return null; } } async getUserByOAuth2Account({ provider, providerAccountId }) { const user = await this.users.findOne({ oauth2Accounts: { $elemMatch: { provider, providerAccountId } } }); if (user) { return { id: user._id, createdAt: user.createdAt, modifiedAt: user.modifiedAt, email: user.email, emailVerifiedAt: user.emailVerifiedAt, oauth2Accounts: user.oauth2Accounts, name: user.name, firstName: user.firstName, preferredName: user.preferredName, address: user.address, active: user.active, lastLogin: user.lastLogin, properties: user.properties, roleIDs: user.roleIDs, paymentProviderCustomers: user.paymentProviderCustomers }; } else { return null; } } async getUsers({ filter, sort, order, cursor, limit }) { var _a, _b, _c; const limitCount = Math.min(limit.count, defaults_1.MaxResultsPerPage); const sortDirection = limit.type === api_1.LimitType.First ? order : -order; const cursorData = cursor.type !== api_1.InputCursorType.None ? cursor_1.Cursor.from(cursor.data) : undefined; const expr = order === api_1.SortOrder.Ascending ? cursor.type === api_1.InputCursorType.After ? '$gt' : '$lt' : cursor.type === api_1.InputCursorType.After ? '$lt' : '$gt'; const sortField = userSortFieldForSort(sort); const cursorFilter = cursorData ? { $or: [ { [sortField]: { [expr]: cursorData.date } }, { _id: { [expr]: cursorData.id }, [sortField]: cursorData.date } ] } : {}; const textFilter = {}; if (filter && JSON.stringify(filter) !== '{}') { textFilter.$and = []; } // TODO: Rename to search if ((filter === null || filter === void 0 ? void 0 : filter.name) !== undefined) { (_a = textFilter.$and) === null || _a === void 0 ? void 0 : _a.push({ name: { $regex: (0, utility_1.escapeRegExp)(filter.name), $options: 'i' } }); } if ((filter === null || filter === void 0 ? void 0 : filter.text) !== undefined) { const columnsToSearch = [ 'name', 'firstName', 'email', 'address.streetAddress', 'address.zipCode', 'address.city' ]; const orConditions = []; const search = filter === null || filter === void 0 ? void 0 : filter.text; const searchTerms = search.split(' '); // iterate user search terms for (const searchTerm of searchTerms) { // iterate columns to be searched for (const column of columnsToSearch) { const orCondition = {}; orCondition[column] = { $regex: (0, utility_1.escapeRegExp)(searchTerm), $options: 'im' }; orConditions.push(orCondition); } } (_b = textFilter.$and) === null || _b === void 0 ? void 0 : _b.push({ $or: orConditions }); } const [totalCount, users] = await Promise.all([ this.users.countDocuments(textFilter, { collation: { locale: this.locale, strength: 2 } }), this.users .aggregate([], { collation: { locale: this.locale, strength: 2 } }) .match(textFilter) .match(cursorFilter) .sort({ [sortField]: sortDirection, _id: sortDirection }) .skip((_c = limit.skip) !== null && _c !== void 0 ? _c : 0) .limit(limitCount + 1) .toArray() ]); const nodes = users.slice(0, limitCount); if (limit.type === api_1.LimitType.Last) { nodes.reverse(); } const hasNextPage = limit.type === api_1.LimitType.First ? users.length > limitCount : cursor.type === api_1.InputCursorType.Before; const hasPreviousPage = limit.type === api_1.LimitType.Last ? users.length > limitCount : cursor.type === api_1.InputCursorType.After; const firstUser = nodes[0]; const lastUser = nodes[nodes.length - 1]; const startCursor = firstUser ? new cursor_1.Cursor(firstUser._id, userDateForSort(firstUser, sort)).toString() : null; const endCursor = lastUser ? new cursor_1.Cursor(lastUser._id, userDateForSort(lastUser, sort)).toString() : null; return { nodes: nodes.map((_a) => { var { _id: id } = _a, user = __rest(_a, ["_id"]); return (Object.assign({ id }, user)); }), pageInfo: { startCursor, endCursor, hasNextPage, hasPreviousPage }, totalCount }; } async updatePaymentProviderCustomers({ userID, paymentProviderCustomers }) { const { value } = await this.users.findOneAndUpdate({ _id: userID }, { $set: { modifiedAt: new Date(), paymentProviderCustomers: paymentProviderCustomers } }, { returnOriginal: false }); if (!value) return null; const { _id: outID } = value; return this.getUserByID(outID); } async addOAuth2Account({ userID, oauth2Account }) { const user = await this.users.findOne({ _id: userID }); if (!user) return null; const accounts = [...user.oauth2Accounts, oauth2Account]; const { value } = await this.users.findOneAndUpdate({ _id: userID }, { $set: { modifiedAt: new Date(), oauth2Accounts: accounts } }, { returnOriginal: false }); if (!value) return null; const { _id: outID } = value; return this.getUserByID(outID); } async deleteOAuth2Account({ userID, providerAccountId, provider }) { const user = await this.users.findOne({ _id: userID }); if (!user) return null; const { value } = await this.users.findOneAndUpdate({ _id: userID }, { $set: { modifiedAt: new Date(), oauth2Accounts: user.oauth2Accounts.filter(account => account.provider !== provider && account.providerAccountId !== providerAccountId) } }, { returnOriginal: false }); if (!value) return null; const { _id: outID } = value; return this.getUserByID(outID); } } exports.MongoDBUserAdapter = MongoDBUserAdapter; function userSortFieldForSort(sort) { switch (sort) { case api_1.UserSort.CreatedAt: return 'createdAt'; case api_1.UserSort.ModifiedAt: return 'modifiedAt'; case api_1.UserSort.Name: return 'name'; case api_1.UserSort.FirstName: return 'firstName'; } } function userDateForSort(user, sort) { switch (sort) { case api_1.UserSort.CreatedAt: return user.createdAt; case api_1.UserSort.ModifiedAt: return user.modifiedAt; case api_1.UserSort.Name: return user.createdAt; case api_1.UserSort.FirstName: return user.createdAt; } } //# sourceMappingURL=user.js.map