@magic.batua/account
Version:
The Account modules powers the user account management features of the Magic Batua platform.
329 lines (308 loc) • 14.2 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Source/Database.js - Postman Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/ionicons.min.css">
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Account.html">Account</a><ul class='methods'><li data-type='method'><a href="Account.html#AddPoints">AddPoints</a></li><li data-type='method'><a href="Account.html#AddReferral">AddReferral</a></li><li data-type='method'><a href="Account.html#CanAuthenticateUsing">CanAuthenticateUsing</a></li><li data-type='method'><a href="Account.html#Delete">Delete</a></li><li data-type='method'><a href="Account.html#Export">Export</a></li><li data-type='method'><a href="Account.html#RedeemPoints">RedeemPoints</a></li><li data-type='method'><a href="Account.html#RemoveReferral">RemoveReferral</a></li><li data-type='method'><a href="Account.html#ResetPassword">ResetPassword</a></li><li data-type='method'><a href="Account.html#SetOTP">SetOTP</a></li><li data-type='method'><a href="Account.html#SetReferrer">SetReferrer</a></li><li data-type='method'><a href="Account.html#Undelete">Undelete</a></li><li data-type='method'><a href="Account.html#UnsetOTP">UnsetOTP</a></li></ul></li><li><a href="Registry.html">Registry</a><ul class='methods'><li data-type='method'><a href="Registry.html#Create">Create</a></li><li data-type='method'><a href="Registry.html#DidResetPassword">DidResetPassword</a></li><li data-type='method'><a href="Registry.html#DidSendOTP">DidSendOTP</a></li><li data-type='method'><a href="Registry.html#HasVerified">HasVerified</a></li><li data-type='method'><a href="Registry.html#IsDuplicate">IsDuplicate</a></li><li data-type='method'><a href="Registry.html#Modify">Modify</a></li><li data-type='method'><a href="Registry.html#Remove">Remove</a></li><li data-type='method'><a href="Registry.html#Retrieve">Retrieve</a></li></ul></li></ul><h3>Modules</h3><ul><li><a href="module-Database.html">Database</a><ul class='methods'><li data-type='method'><a href="module-Database.html#~Find">Find</a></li><li data-type='method'><a href="module-Database.html#~FindAndReplace">FindAndReplace</a></li><li data-type='method'><a href="module-Database.html#~GetAccountByID">GetAccountByID</a></li><li data-type='method'><a href="module-Database.html#~GetReferrer">GetReferrer</a></li><li data-type='method'><a href="module-Database.html#~Insert">Insert</a></li><li data-type='method'><a href="module-Database.html#~IsDuplicate">IsDuplicate</a></li><li data-type='method'><a href="module-Database.html#~UpdateInPlace">UpdateInPlace</a></li></ul></li><li><a href="module-Source.html">Source</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">Source/Database.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>"use strict";
/**
* @module Database
* @overview Defines the database manipulation functions used by the `Registry` module.
*
* @author Animesh Mishra <hello@animesh.ltd>
* @copyright © 2018 Animesh Ltd. All Rights Reserved.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const Chai = require("chai");
const Mongo = require("mongodb");
const Account_1 = require("./Account");
const Source_1 = require("./Source");
const error_1 = require("@magic.batua/error");
const expect = Chai.expect;
const AccountCollection = "Users";
/**
* @exports Database
* The `Database` module powers the database read/write capabilities of the Magic Batua
* platform.
*/
exports.description = "Powers the database read/write capabilities of the Magic Batua platform.";
/**
* Looks up the `phone` number in the user account registry.
*
* @param {string} phone Phone number to be searched
* @param {Mongo.Db} db Database to be scoured
*
* @returns {Promise<Account | null>} An `Account` object if a match is found. If a
* match is found but the referrer account has been soft-deleted, returns `null`. If
* no match is found, returns `null`.
*
* @throws {ExternalError} If the search operation fails, a `424 Failed Dependency`
* error is thrown.
*/
async function Find(phone, db) {
try {
let filter = { phone: phone };
let document = await db.collection(AccountCollection).findOne(filter);
// If no document is found, return null
if (document == null) {
return null;
}
else if (document.isDeleted && document.recoverBy <= Date.now()) {
return null;
}
else {
return new Account_1.Account(document);
}
}
catch (exception) {
throw new error_1.ExternalError("Database search crashed unexpectedly.", "MongoDB", exception.toString());
}
}
exports.Find = Find;
/**
* Finds a user account registry entry that matches the given account information and
* replaces that document with the `account` document provided.
*
* @param {Account} account Phone number to be searched
* @param {Mongo.Db} db Database to be scoured
*
* @returns {Promise<Account>} The updated `Account` object if a match is found and
* successfully replaced by the document provided.
*
* @throws {ExternalError} If the operation fails, a `424 Failed Dependency` error is thrown.
*/
async function FindAndReplace(account, db) {
try {
let filter = { _id: account._id };
let response = await db.collection(AccountCollection).findOneAndReplace(filter, account);
// If update was successful, return the updated Account instance
if (response.ok) {
return new Account_1.Account(response.value);
}
else {
throw response.lastErrorObject;
}
}
catch (exception) {
throw new error_1.ExternalError("Database search crashed unexpectedly.", "MongoDB", exception.toString());
}
}
exports.FindAndReplace = FindAndReplace;
/**
* Given a user `id`, retrieves the full account information stored against that `id` in
* the database.
*
* @param {string} id Magic Batua user ID
* @param {Mongo.Db} db Database to be searched
*
* @returns {Promise<Account | null>} An `Account` object if a match is found. If a
* match is found but the referrer account has been soft-deleted, returns `null`. If
* no match is found, returns `null`.
*
* @throws {ExternalError} If the search operation fails, a `424 Failed Dependency`
* error is thrown.
*/
async function GetAccountByID(id, db) {
try {
let filter = { _id: new Mongo.ObjectId(id) };
let document = await db.collection(AccountCollection).findOne(filter);
// If no document is found, return null
if (document == null) {
return null;
}
else if (document.isDeleted && document.recoverBy <= Date.now()) {
return null;
}
else {
return new Account_1.Account(document);
}
}
catch (exception) {
throw new error_1.ExternalError("Database search crashed unexpectedly.", "MongoDB", exception.toString());
}
}
exports.GetAccountByID = GetAccountByID;
/**
* When a user is referred to Magic Batua by their friends and family, their signup
* request contains an `inviteCode` that helps us identify the referrer in our systems.
* This is the method that does that heavy lifting.
*
* This method searches the database to find the `Account` having the same `referralCode`
* property as the given `inviteCode`. If a match is found, it is deemed the rightful
* referrer and returned to the calling scope.
*
* @param {string} inviteCode Referral code used at signup
* @param {Mongo.Db} db Database to be scoured
*
* @returns {Promise<Account | null>} An `Account` object if a referrer is found. If
* a match is found but the referrer account has been soft-deleted, returns `null`. If
* no match is found, returns `null`.
*
* @throws {ExternalError} If the search operation fails, a `424 Failed Dependency`
* error is thrown.
*/
async function GetReferrer(inviteCode, db) {
try {
let filter = { referralCode: inviteCode };
let result = await db.collection(AccountCollection).findOne(filter);
// If no referrer is found, return null
if (result == null) {
return null;
}
else if (result.isDeleted && result.recoverBy <= Date.now()) {
return null;
}
else {
return new Account_1.Account(result);
}
}
catch (exception) {
throw new error_1.ExternalError("Database search crashed unexpectedly.", "MongoDB", exception.toString());
}
}
exports.GetReferrer = GetReferrer;
/**
* Inserts the given `account` document into the MongoDB database instance
* held by `db`. No validation checks are run before writing the object to
* database.
*
* @param {Account} account `Account` object to be written to database
* @param {Mongo.Db} db The recipient MongoDB database
*
* @returns {Promise<Account>} A fully instantiated `Account` object
* @throws {ExternalError} If the write operation fails, a `424 Failed Dependency`
* error is thrown.
*/
async function Insert(account, db) {
try {
let response = await db.collection(AccountCollection).insertOne(account);
// Check whether the operation executed correctly
expect(response.result.ok).to.be.equal(1, "Account: Database.Insert() returned a non-ok result.");
// Return the account object
return new Account_1.Account(response.ops.pop(), Source_1.Source.Database);
}
catch (exception) {
throw new error_1.ExternalError("Couldn't write object to database.", "MongoDB", exception.toString());
}
}
exports.Insert = Insert;
/**
* Checks whether the given `account` information is already registered with us.
*
* @param {Account} account Account information
* @param {Mongo.Db} db Database to be scoured
*
* @returns {Promise<boolean>} `true` if a matching account is found. If a match is found
* but the account has been soft-deleted, returns `false`. If no match is found,
* returns `false`.
*
* @throws {ExternalError} If the search operation fails, a `424 Failed Dependency`
* error is thrown.
*/
async function IsDuplicate(account, db) {
try {
let filter = { phone: account.phone };
let fields = { fields: {
isDeleted: true,
recoverBy: true
} };
let result = await db.collection(AccountCollection).findOne(filter, fields);
// If no matching document is found, return false
if (result == null) {
return false;
}
else if (result.isDeleted && result.recoverBy <= Date.now()) {
return false;
}
else {
return true;
}
}
catch (exception) {
throw new error_1.ExternalError("Database search crashed unexpectedly.", "MongoDB", exception.toString());
}
}
exports.IsDuplicate = IsDuplicate;
/**
* Updates the database object corresponding to the given `_id` in place. Doesn't run data
* validation checks, so use very carefully and sparsely. Most of the update operations in the
* software are done through the `Database.FindAndReplace()` method. Use that.
*
* **Only allows updates for `name`, `email` or `phone`.**
*
* If the `query` parameter contains a Magic Points transaction entry, then the entry is
* pushed to the `pointsLedger.transactions` array.
*
* @param {string} id Magic Batua user `_id`
* @param {any} query A JSON containing key-value pairs that should be updated.
* @param {Mongo.Db} db MongoDB database instance
*
* @throws {ExternalError} If the operation fails, a `424 Failed Dependency` error is thrown.
*/
async function UpdateInPlace(id, query, db) {
try {
let filter = { _id: id };
let updates;
let operations;
if (query.name) {
updates.name = query.name;
}
if (query.email) {
updates.email = query.email;
}
if (query.phone) {
updates.phone = query.phone;
}
// If a points transaction is supplied in the query, then push it to the transaction array
if (query.pointsTransaction) {
operations = {
$set: updates,
$push: { "pointsLedger.transactions": query.pointsTransaction }
};
}
else {
operations = {
$set: updates
};
}
let response = await db.collection(AccountCollection).updateOne(filter, operations);
expect(response.result.ok).to.equal("1", "Database update returned a non-true result.");
}
catch (exception) {
throw new error_1.ExternalError("Database update crashed unexpectedly.", "MongoDB", exception.toString());
}
}
exports.UpdateInPlace = UpdateInPlace;
//# sourceMappingURL=Database.js.map</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated at Mon Mar 19 2018 22:39:23 GMT+0530 (IST)
</footer>
<script>prettyPrint();</script>
<script src="scripts/linenumber.js"></script>
</body>
</html>