UNPKG

fully-api

Version:

API framework for Fully Stacked, LLC REST-ful APIs

724 lines 33.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Accounts = void 0; /*jshint expr: true, es5: true, unused:false */ const ErrorObj_1 = require("../../services/ErrorObj"); // =============================================================================== // ACCOUNTS WEB SERVICE CALLS v1.0.0 // =============================================================================== let crypto = require('crypto'); // TWILLO SMS OTM SETUP const accountSid = process.env.TWILIO_ACCOUNT_SID; const authToken = process.env.TWILIO_AUTH_TOKEN; const serviceID = process.env.TWILIO_SERVICE_ID; const twilioActive = process.env.TWILIO_ACTIVE ? process.env.TWILIO_ACTIVE.toLowerCase() == 'true' : false; let twilio; if (twilioActive) { twilio = require('twilio')(accountSid, authToken); } else { twilio = {}; } let Q = require('q'); let dataAccess; let utilities; let accessControl; let serviceRegistration; let settings; let models; let config; class Accounts { constructor(db, utils, ac, sr, st, m, c) { config = c; models = m; settings = st; serviceRegistration = sr; accessControl = ac; utilities = utils; dataAccess = db; } getUser(req, callback) { let deferred = Q.defer(); let username = (typeof (req.body.username) == 'undefined' || req.body.username === null) ? req.body.email.toLowerCase() : req.body.username.toLowerCase(); dataAccess.findUser(username, null, true) .then(function (user) { if (user.data) { user = user.data; } deferred.resolve(user); }) .fail(function (err) { if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { deferred.reject(err.AddToError(__filename, 'getUser')); } else { let errorObj = new ErrorObj_1.ErrorObj(500, 'a2038', __filename, 'getUser', 'error getting user', 'Error getting user', err); deferred.reject(errorObj); } }); deferred.promise.nodeify(callback); return deferred.promise; } getToken(callback) { let deferred = Q.defer(); dataAccess.getAllSessions() .then(function (active_sessions) { let tokenIsGood = false; let token; while (!tokenIsGood) { token = crypto.randomBytes(48).toString('hex'); let sessions = active_sessions.filter(function (inSysObj) { return (inSysObj.object_type === 'session' && inSysObj.token === token); }); if (sessions === null || sessions.length === 0) { tokenIsGood = true; } else { tokenIsGood = false; } } deferred.resolve(token); }) .fail(function (err) { if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { if (err.message === 'no results found') { let token = crypto.randomBytes(48).toString('hex'); deferred.resolve(token); } else { deferred.reject(err.AddToError(__filename, 'getToken')); } } else { let errorObj = new ErrorObj_1.ErrorObj(500, 'a1036', __filename, 'getToken', 'error getting token', 'Error getting token', err); deferred.reject(errorObj); } }); deferred.promise.nodeify(callback); return deferred.promise; } twillio_verify_code(to_value, sms_otp) { let deferred = Q.defer(); if ((process.env.TWILIO_ENV == 'sandbox' && process.env.NODE_ENV != 'production') || (to_value == '+18006927753' && process.env.NODE_ENV == 'production')) { if (sms_otp == '6666') { let errorObj = new ErrorObj_1.ErrorObj(400, 'a100032', __filename, 'otp_signIn', 'TWILLIO SANDBOX MODE otp not valid. perhaps it expired', 'TWILLIO SANDBOX MODE invalid code', null); deferred.reject(errorObj); } else { if (process.env.NODE_ENV == 'production' && sms_otp != '1234567') { let errorObj = new ErrorObj_1.ErrorObj(400, 'a100032', __filename, 'otp_signIn', 'code not valid. perhaps it expired', 'invalid code, please try again', null); deferred.reject(errorObj); } else { deferred.resolve({ valid: true }); } } } else { twilio.verify.services(serviceID) .verificationChecks .create({ to: to_value, code: sms_otp }) .then(function (verification_check) { if (verification_check.valid == true) { // found their account --- start their session and return token deferred.resolve(verification_check); } else { let errorObj = new ErrorObj_1.ErrorObj(400, 'a10003', __filename, 'otp_signIn', 'otp not valid. perhaps it expired', 'invalid code', null); deferred.reject(errorObj); } }) .catch(function (err) { let errorObj = new ErrorObj_1.ErrorObj(500, 'a10004', __filename, 'otp_signIn', 'otp validation with twilio failed.', 'Validating code failed. Please request a new code.', null); deferred.reject(errorObj); }); } return deferred.promise; } twillio_send_code(to_value) { let deferred = Q.defer(); if ((process.env.TWILIO_ENV == 'sandbox' && process.env.NODE_ENV != 'production') || (to_value == '+18006927753' && process.env.NODE_ENV == 'production')) { deferred.resolve({ status: 'pending' }); } else { twilio.verify.services(serviceID) .verifications .create({ to: to_value, channel: 'sms' }) .then(function (verification) { deferred.resolve(verification); }) .catch(function (err) { deferred.reject(err); }); } return deferred.promise; } } exports.Accounts = Accounts; ; Accounts.prototype.get = { user(req, callback) { let deferred = Q.defer(); delete req.this_user.password; delete req.this_user.client_secret; delete req.this_user.forgot_password_tokens; delete req.this_user.salt; delete req.this_user.user_id; delete req.this_user.auth_id; deferred.resolve(req.this_user); deferred.promise.nodeify(callback); return deferred.promise; }, }; Accounts.prototype.post = { validate_token(req, callback) { let deferred = Q.defer(); accessControl.validateToken(req.headers[settings.data.token_header], true) .then(function (res) { deferred.resolve({ valid: res.is_valid }); }) .fail(function (err) { deferred.resolve({ valid: false }); }); deferred.promise.nodeify(callback); return deferred.promise; }, forgot_password(req, callback) { let deferred = Q.defer(); let args = req.body; let email = args.email; let username = args.username; let validArgs = false; if (username != null && username !== '') { validArgs = true; } else if (email != null && email !== '') { validArgs = true; } if (validArgs) { dataAccess.findUser(email, username, true) .then(function (userObj) { if (userObj.is_locked) { let errorObj = new ErrorObj_1.ErrorObj(403, 'ta0001', __filename, 'forgotPassword', 'bsuser is locked', 'Unauthorized', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } return [userObj, utilities.getUID()]; }) .spread(function (userObj, tkn) { let reset_link = process.env.reset_password_link || ""; reset_link = reset_link + "/" + tkn; if (process.env.NODE_ENV !== 'local') { return [userObj, tkn, utilities.sendMailTemplate(userObj.email, 'Password Reset', 'forgot_password', { 'link': reset_link })]; } else { return [userObj, tkn, null]; } }) .spread(function (userObj, tkn, mail_res) { if (userObj.forgot_password_tokens === undefined || userObj.forgot_password_tokens === null) { userObj.forgot_password_tokens = [tkn]; } else { userObj.forgot_password_tokens.push(tkn); } return [tkn, dataAccess.updateRow('fsapi_user_auth', { 'forgot_password_tokens': userObj.forgot_password_tokens }, userObj.id, 'user_id')]; }) .spread(function (tkn, save_res) { // ADD EVENT TO SESSION let resolveObj = { 'success': true }; if (process.env.NODE_ENV == 'local') { resolveObj.token = tkn; } deferred.resolve(resolveObj); }) .fail(function (err) { if (err.err_code == "da0200") { deferred.resolve({ 'success': true, 'no_user': true }); } else if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { err.setMessages('error generating password reset link', 'Problem generating email and link to reset password'); deferred.reject(err.AddToError(__filename, 'forgotPassword')); } else { let errorObj = new ErrorObj_1.ErrorObj(500, 'ta0002', __filename, 'forgotPassword', 'error generating password reset link', 'Problem generating email and link to reset password', err); deferred.reject(errorObj); } }); } else { let errorObj = new ErrorObj_1.ErrorObj(400, 'ta0003', __filename, 'forgotPassword', 'must supply username or email associated with this bsuser'); deferred.reject(errorObj); } deferred.promise.nodeify(callback); return deferred.promise; }, reset_password(req, callback) { let deferred = Q.defer(); let args = req.body; let tkn = args.token; let password = args.password; dataAccess.getUserByForgotPasswordToken(tkn) .then(function (userObjs) { let userObj; if (userObjs.length > 0) { userObj = userObjs[0]; if (userObj.data) { userObj = userObj.data; } // IF USER IS LOCKED, BAIL OUT if (userObj.is_locked) { let errorObj = new ErrorObj_1.ErrorObj(403, 'a2007', __filename, 'resetPassword', 'bsuser is locked', 'Unauthorized', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } let cryptoCall = Q.denodeify(crypto.randomBytes); return [userObj, cryptoCall(48)]; } else { let errorObj = new ErrorObj_1.ErrorObj(401, 'a0033', __filename, 'resetPassword', 'token not found'); deferred.reject(errorObj); } }) .spread(function (userObj, buf) { let salt = buf.toString('hex'); let saltedPassword = password + salt; let hashedPassword = crypto.createHash('sha256').update(saltedPassword).digest('hex'); let update_fields = { 'password': hashedPassword, 'salt': salt, 'forgot_password_tokens': [] }; userObj.password = hashedPassword; userObj.salt = salt; userObj.forgot_password_tokens = []; return dataAccess.updateRow('fsapi_user_auth', update_fields, userObj.id, 'user_id'); }) .then(function () { let resolveObj = { 'success': true }; deferred.resolve(resolveObj); }) .fail(function (err) { if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { err.setMessages('Problem reseting password'); deferred.reject(err.AddToError(__filename, 'resetPassword')); } else { let errorObj = new ErrorObj_1.ErrorObj(500, 'a1033', __filename, 'resetPassword', 'error reseting password', 'Problem reseting password', err); deferred.reject(errorObj); } }); deferred.promise.nodeify(callback); return deferred.promise; }, sign_in(req, callback) { let deferred = Q.defer(); let body = req.body; let password = body.password; let clientInfo = req.headers['user-agent']; if (utilities.isNullOrUndefined(body.username) && utilities.isNullOrUndefined(body.email)) { let errorObj = new ErrorObj_1.ErrorObj(400, 'a00001', __filename, 'signIn', 'Please include username or email to sign in.'); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } Accounts.prototype.getUser(req) .then(function (userObj) { // IF USER IS LOCKED, BAIL OUT if (userObj.is_locked) { let errorObj = new ErrorObj_1.ErrorObj(403, 'a2004', __filename, 'signin', 'bsuser is locked', 'Unauthorized', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } // GOT A USER, MAKE SURE THERE IS A STORED SALT let salt = userObj.salt; if (salt === null) { let errorObj = new ErrorObj_1.ErrorObj(500, 'a0025', __filename, 'signIn', 'error retrieving salt for this user'); deferred.reject(errorObj); } let stored_password = userObj.password; if (stored_password === null) { let errorObj = new ErrorObj_1.ErrorObj(500, 'a0026', __filename, 'signIn', 'error retrieving password for this user'); deferred.reject(errorObj); } // SALT AND HASH PASSWORD let saltedPassword = password + userObj.salt; let hashedPassword = crypto.createHash('sha256').update(saltedPassword).digest('hex'); // CHECK IF HASHES MATCH if (hashedPassword === stored_password) { return [userObj, Accounts.prototype.getToken()]; } else { let errorObj = new ErrorObj_1.ErrorObj(401, 'a0027', __filename, 'signIn', 'Invalid credentials'); deferred.reject(errorObj); } }) .spread(function (userObj, tkn) { return [tkn, userObj, dataAccess.createSession(tkn, userObj.id, userObj.username, clientInfo)]; }) .spread(function (tkn, userObj, newSess) { let returnObj = {}; returnObj[settings.data.token_header] = tkn; let uiKeys = Object.keys(userObj); for (let uiIdx = 0; uiIdx < uiKeys.length; uiIdx++) { returnObj[uiKeys[uiIdx]] = userObj[uiKeys[uiIdx]]; } delete returnObj.password; delete returnObj.salt; delete returnObj.object_type; delete returnObj.created_at; delete returnObj.updated_at; delete returnObj.forgot_password_tokens; delete returnObj.is_active; deferred.resolve(returnObj); }) .fail(function (err) { if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { err.setMessages('authentication failed', 'authentication failed'); err.setStatus(401); deferred.reject(err.AddToError(__filename, 'signIn')); } else { let errorObj = new ErrorObj_1.ErrorObj(401, 'a0028', __filename, 'signIn', 'authentication failed', 'authentication failed', err); deferred.reject(errorObj); } }); deferred.promise.nodeify(callback); return deferred.promise; }, sign_out(req, callback) { let deferred = Q.defer(); let token = req.headers[settings.data.token_header]; dataAccess.findSessionByToken(token) .then(function (session) { utilities.invalidateSession(session) .then(() => { deferred.resolve({ success: true }); }) .fail((err) => { deferred.reject(err); }); }) .fail(function (err) { if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { err.setMessages('authentication failed', 'authentication failed'); err.setStatus(401); deferred.reject(err.AddToError(__filename, 'signIn')); } else { let errorObj = new ErrorObj_1.ErrorObj(401, 'a0028', __filename, 'signIn', 'authentication failed', 'authentication failed', err); deferred.reject(errorObj); } }); deferred.promise.nodeify(callback); return deferred.promise; }, sign_up(req, callback) { let deferred = Q.defer(); let username = utilities.isNullOrUndefined(req.body.username) ? req.body.email.toLowerCase() : req.body.username.toLowerCase(); let password = req.body.password; let firstname = (utilities.isNullOrUndefined(req.body.firstname) ? '' : req.body.firstname); let lastname = (utilities.isNullOrUndefined(req.body.lastname) ? '' : req.body.lastname); let roles = ['default']; let email = req.body.email; if (utilities.emailFormatValid(email)) { let errorObj = new ErrorObj_1.ErrorObj(400, 'a0029', __filename, 'signUp', 'invalid email address'); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } dataAccess.verifyUserAttributeUnique('email', email) .then(function () { return dataAccess.verifyUserAttributeUnique('username', username); }) .then(function () { let cryptoCall = Q.denodeify(crypto.randomBytes); return cryptoCall(48); }) .then(function (buf) { let salt = buf.toString('hex'); let saltedPassword = password + salt; let hashedPassword = crypto.createHash('sha256').update(saltedPassword).digest('hex'); let userObj = { 'username': username, 'firstname': firstname, 'lastname': lastname, 'email': email, 'salt': salt, 'password': hashedPassword, 'security_roles': roles, 'is_active': true, 'is_locked': false }; dataAccess.createUser(userObj) .then(function (created_userObj) { delete created_userObj.password; delete created_userObj.salt; deferred.resolve(created_userObj); }) .fail(function (err) { deferred.reject(err); }); }) .fail(function (err) { if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { deferred.reject(err.AddToError(__filename, 'signUp')); } else { let errorObj = new ErrorObj_1.ErrorObj(500, 'a0030', __filename, 'signUp', 'error signing up', 'Error', err); deferred.reject(errorObj); } }); deferred.promise.nodeify(callback); return deferred.promise; }, // TWILLIO SMS OTP ENDPOINTS sms_otp(req, callback) { let deferred = Q.defer(); let params = req.body; let raw_country_code = params.country_code || 1; let country_code = '+' + raw_country_code.toString(); let phone_number = params.phone_number.toString(); let to_value = country_code + phone_number; if (country_code == '+1' && phone_number.length !== 10) { let errorObj = new ErrorObj_1.ErrorObj(400, 'a10001', __filename, 'sms_otp', 'phone number must be 10 digit', 'invalid US phone number. must be 10 digits', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } let query = "SELECT * FROM bsuser where phone_country = $1 AND phone_number = $2"; let query_params = [raw_country_code, phone_number]; dataAccess.ExecutePostgresQuery(query, query_params) .then(function (db_res) { Accounts.prototype.twillio_send_code(to_value) .then(function (verification) { let resObj = { verify_status: verification.status, country_code: raw_country_code.toString(), phone_number, }; if (db_res.results.length > 0) { resObj.account_exists = true; } else { resObj.account_exists = false; } deferred.resolve(resObj); }) .catch(function (err) { deferred.reject(err); }); }) .fail(function (err) { deferred.reject(err); }); deferred.promise.nodeify(callback); return deferred.promise; }, otp_signIn(req, callback) { let deferred = Q.defer(); let body = req.body; let sms_otp = body.otp_code; let raw_country_code = body.country_code || 1; let country_code = '+' + raw_country_code.toString(); let phone_number = body.phone_number.toString(); let firstname = body.firstname; let lastname = body.lastname; let email = body.email; let ts_cs_accepted = body.ts_cs_accepted || true; let is_18_plus = body.is_18_plus || true; let clientInfo = req.headers['user-agent']; let to_value = country_code + phone_number; if (country_code == '+1' && phone_number.length !== 10) { let errorObj = new ErrorObj_1.ErrorObj(400, 'a20001', __filename, 'otp_signIn', 'phone number must be 10 digit', 'invalid US phone number. must be 10 digits', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } let query = "SELECT * FROM fsapi_user where phone_country_code = $1 AND phone_number = $2"; let query_params = [raw_country_code, phone_number]; dataAccess.ExecutePostgresQuery(query, query_params) .then(function (db_res) { // if more than one error, if (db_res.results.length > 1) { let errorObj = new ErrorObj_1.ErrorObj(400, 'a20002', __filename, 'otp_signIn', 'multiple accounts', 'Multiple accounts found with this phone number. Please contact The Meetery so they can assist you.', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } else if (db_res.results.length == 1) { let userObj = (db_res.results[0]).data; Accounts.prototype.twillio_verify_code(to_value, sms_otp) .then(function (verification_check) { if (verification_check.valid == true) { // found their account --- start their session and return token Accounts.prototype.getToken() .then(function (tkn) { dataAccess.createSession(tkn, userObj.id, userObj.username, clientInfo) .then(function (sess_res) { deferred.resolve(sess_res); }) .fail(function (err) { deferred.reject(err); }); }) .fail(function (err) { deferred.reject(err); }); } else { let errorObj = new ErrorObj_1.ErrorObj(400, 'a10003', __filename, 'otp_signIn', 'otp not valid. perhaps it expired', 'invalid code', null); deferred.reject(errorObj); } }) .catch(function (err) { let errorObj = new ErrorObj_1.ErrorObj(500, 'a10004', __filename, 'otp_signIn', 'otp validation with twilio failed.', 'Validating code failed. Please request a new code.', null); deferred.reject(errorObj); }); } else { if (ts_cs_accepted != true) { let errorObj = new ErrorObj_1.ErrorObj(400, 'ac0330', __filename, 'signUp', 'Must accept terms and conditions.', 'Must accept terms and conditions.', {}); deferred.reject(errorObj); } else if (is_18_plus != true) { let errorObj = new ErrorObj_1.ErrorObj(400, 'ac0332', __filename, 'signUp', 'Must be 18 years or older.', 'Must be 18 years or older.', {}); deferred.reject(errorObj); } else { dataAccess.verifyUserAttributeUnique('email', email) .then(function () { Accounts.prototype.twillio_verify_code(to_value, sms_otp) .then(function (verification_check) { if (verification_check.valid == true) { // TODO no account found -- create new account. let userObj = { 'username': phone_number, 'phone_number': phone_number, 'phone_country_code': country_code, 'created_at': new Date(), 'first': firstname, 'lastname': lastname, 'email': email, 'security_roles': ['default'], 'ts_cs_accepted': ts_cs_accepted, 'is_18_plus': is_18_plus, 'is_locked': false, 'is_active': true }; dataAccess.createUser(userObj) .then(function (created_userObj) { Accounts.prototype.getToken() .then(function (tkn) { dataAccess.createSession(tkn, created_userObj.id, created_userObj.username, clientInfo) .then(function (sess_res) { deferred.resolve(sess_res); }) .fail(function (err) { deferred.reject(err); }); }) .fail(function (err) { deferred.reject(err); }); }) .fail(function (err) { deferred.reject(err); }); } else { let errorObj = new ErrorObj_1.ErrorObj(400, 'a10003', __filename, 'otp_signIn', 'otp not valid. perhaps it expired', 'invalid code', null); deferred.reject(errorObj); } }) .catch(function (err) { let errorObj = new ErrorObj_1.ErrorObj(500, 'a10004', __filename, 'otp_signIn', 'otp validation with twilio failed.', 'Validating code failed. Please request a new code.', null); deferred.reject(errorObj); }); }) .fail(function (err) { if (err.err_code == 'u0054' || err.err_code == 'u0055') { err.display_message = 'A user already exists with the email provided.'; err.message = 'A user already exists with the email provided.'; deferred.reject(err); } else if (err !== undefined && err !== null && typeof (err.AddToError) == 'function') { deferred.reject(err.AddToError(__filename, 'createStandardUser')); } else { let errorObj = new ErrorObj_1.ErrorObj(500, 'ac0330', __filename, 'createStandardUser', 'error signing up', 'Error', err); deferred.reject(errorObj); } }); } } }) .fail(function (err) { deferred.reject(err); }); deferred.promise.nodeify(callback); return deferred.promise; } }; Accounts.prototype.patch = { onesignal_token(req, callback) { // USE IF REGISTERING ONESIGNAL DEVICE IDs FOR PUSH NOTIFICATIONS. MUST ADD onesignal_user_id to fsapi_user_auth table first let deferred = Q.defer(); let user = req.this_user; let onesignal_user_id = req.body.onesignal_user_id; let query = "UPDATE fsapi_user_auth SET onesignal_user_id = null WHERE onesignal_user_id = $1 RETURNING user_id, onesignal_user_id"; dataAccess.executePostgresQuery(query, [onesignal_user_id]) .then(function (db_res) { let query = "UPDATE fsapi_user_auth SET onesignal_user_id = $1 WHERE id = $2 RETURNING id, profile_id, onesignal_user_id"; dataAccess.ExecutePostgresQuery(query, [onesignal_user_id, user.id]) .then(function (db_res) { deferred.resolve(db_res.results[0]); }) .fail(function (err) { let errorObj = new ErrorObj_1.ErrorObj(500, 'ost_0001', __filename, 'onesignal_token', 'getting account from token failed.', 'Updating One Signal token failed. Please try again later.', err); deferred.reject(errorObj); }); }) .fail(function (err) { let errorObj = new ErrorObj_1.ErrorObj(500, 'ost_0001', __filename, 'onesignal_token', 'getting account from token failed.', 'Updating One Signal token failed. Please try again later.', err); deferred.reject(errorObj); }); deferred.promise.nodeify(callback); return deferred.promise; }, password(req, callback) { let user = req.this_user; // USE IF REGISTERING ONESIGNAL DEVICE IDs FOR PUSH NOTIFICATIONS. MUST ADD onesignal ID to fsapi_user_auth table first let deferred = Q.defer(); let password = req.body.password; if (user.is_locked) { let errorObj = new ErrorObj_1.ErrorObj(403, 'a2004', __filename, 'signin', 'bsuser is locked', 'Unauthorized', null); deferred.reject(errorObj); deferred.promise.nodeify(callback); return deferred.promise; } // GOT A USER, MAKE SURE THERE IS A STORED SALT let salt = user.salt; if (salt === null) { let errorObj = new ErrorObj_1.ErrorObj(500, 'a0025', __filename, 'signIn', 'error retrieving salt for this user'); deferred.reject(errorObj); } // SALT AND HASH PASSWORD let saltedPassword = password + user.salt; let hashedPassword = crypto.createHash('sha256').update(saltedPassword).digest('hex'); dataAccess.updateRow('fsapi_user_auth', { 'password': hashedPassword }, user.id, 'user_id') .then(function (res) { deferred.resolve(user); }) .fail(function (err) { deferred.reject(err); }); deferred.promise.nodeify(callback); return deferred.promise; } }; Accounts.prototype.delete = {}; //# sourceMappingURL=accounts_1_0_0.js.map