<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 0xSaurav</title>
    <description>The latest articles on DEV Community by 0xSaurav (@0xsaurav).</description>
    <link>https://dev.to/0xsaurav</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F793454%2F0a663c9f-05ae-4784-9d71-7abf634e3541.png</url>
      <title>DEV Community: 0xSaurav</title>
      <link>https://dev.to/0xsaurav</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/0xsaurav"/>
    <language>en</language>
    <item>
      <title>Build a Modern Finance App with MongoDB: Concept to MVP in 6 days</title>
      <dc:creator>0xSaurav</dc:creator>
      <pubDate>Fri, 14 Jan 2022 04:58:58 +0000</pubDate>
      <link>https://dev.to/0xsaurav/neobanking-with-mongodb-15fd</link>
      <guid>https://dev.to/0xsaurav/neobanking-with-mongodb-15fd</guid>
      <description>&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;Building Financial Applications are challenging. A typical application requires good design of db-schemas, data read-write and concise front-end to back-end interactions. Building such appplications generally takes a few months of development-time effort. &lt;/p&gt;

&lt;p&gt;With MongoDB Atlas and Realm - this can be achieved in under a weeks time and a MVP level application can be ready for end user testing. &lt;/p&gt;

&lt;p&gt;Front-end is developed using ReactJS and is Mobile Responsive. &lt;/p&gt;

&lt;p&gt;This submission covers the various steps to setup a Fintech Neobank application. It includes User Registration, Contact Management, Making and Requesting Fund Transfers, Download Account Statements, Notifications etc. It does not include actual fund transfers - and current intergation is only with Stellar Testnet - however this can be easily achieved by linking with a Payment Gateway Service or Stellar Mainnet or any other Blockchain Network for actual fund transfers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fq2HHzAP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9wyu6an5z4kujjvwxoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fq2HHzAP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9wyu6an5z4kujjvwxoa.png" alt="Image description" width="880" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Action Star&lt;/p&gt;

&lt;h3&gt;
  
  
  Neobank Financial Application
&lt;/h3&gt;

&lt;p&gt;The suitable audience for this is Small-Medium Businesses and  Owners and Independent Professional and anyone who would like a better control over their finances, manage multiple accounts in a single window.&lt;/p&gt;

&lt;p&gt;The application allows KYC completed users to login. After authentication, it provides a unified login interface and account selection (personal, business). Inside, user has access to following features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Dashboard with account balance, various action short-cuts, Pending Payments and Collections&lt;/li&gt;
&lt;li&gt;Contacts List (personal, business)&lt;/li&gt;
&lt;li&gt;Transfers List - record or all transactions with filters to search (the welcome bonus transaction is seen)&lt;/li&gt;
&lt;li&gt;Accounts - List of all accounts - Stellar, Fiat etc&lt;/li&gt;
&lt;li&gt;Reports - for downloading statements&lt;/li&gt;
&lt;li&gt;Solutions - this is a list of various offerings personalized for the customer. (we are showing all options here), however, for example, the business user will get option to open additional accounts for customer invoice payment collections or for managing payroll accounts. These are to be controlled by the subscription plans purchased by the user - depending on number of customers, suppliers and team members, contacts etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FvqwDG2H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y88gh5oq17tuf0g5bj4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FvqwDG2H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y88gh5oq17tuf0g5bj4j.png" alt="User Dashboard" width="880" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transfers&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5nv33hq8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xiqpderhckxa430065sx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5nv33hq8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xiqpderhckxa430065sx.png" alt="Al Transactions" width="880" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact Transaction Summary&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J1welXjw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/72huer7rtvsarhibbnsy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J1welXjw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/72huer7rtvsarhibbnsy.png" alt="Contact View" width="880" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo Video
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://vimeo.com/666143818/c471f0426d"&gt;https://vimeo.com/666143818/c471f0426d&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Try Online
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://neobank-demo.web.app/"&gt;https://neobank-demo.web.app/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/finnovateinc/neobank-demo"&gt;https://github.com/finnovateinc/neobank-demo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Trigger-based Automatic Alerts for Transactions and Account Balance Updates&lt;/li&gt;
&lt;li&gt;Triggers-based actions for Team Salary Payments on Specific Day of Month&lt;/li&gt;
&lt;li&gt;Triggers-based actions for Holiday and Bonus Payments&lt;/li&gt;
&lt;li&gt;Web and Mobile Ready&lt;/li&gt;
&lt;li&gt;Can be integrated with any Fiat (Bank or Payment Gateway Integration) or Blockchain Network via SDKs&lt;/li&gt;
&lt;li&gt;Multi-Signature Support can be added for Business Accounts&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>atlashackathon</category>
    </item>
    <item>
      <title>Secure Your Applications with MongoDB in 15 mins</title>
      <dc:creator>0xSaurav</dc:creator>
      <pubDate>Fri, 14 Jan 2022 04:58:26 +0000</pubDate>
      <link>https://dev.to/0xsaurav/secure-your-applications-with-mongodb-1jmm</link>
      <guid>https://dev.to/0xsaurav/secure-your-applications-with-mongodb-1jmm</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;One-time password (OTP) systems provide a mechanism for logging on to a network, service, web and/or mobile application using a unique password that can only be used once, as the name suggests. In many cases such as Financial Applications, it is also used for a 2-Factor Authentication in addition to the static account password.&lt;/p&gt;

&lt;p&gt;Other cases include verification of user accounts - email, mobile numbers during application signup. &lt;/p&gt;

&lt;p&gt;For any project, one needs to utilize various third-party applications for the OTP Service. Using MongoDB Atlas, MongoDB Realm (Functions, Triggers), it is possible to setup our own one-time passcode service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Action Star&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;The setup includes MongoDB Atlas, MongoDB Realm. &lt;br&gt;
Other libraries: Nodemailer, GMail Account&lt;/p&gt;

&lt;p&gt;Setup Time: 20-30 mins&lt;/p&gt;
&lt;h3&gt;
  
  
  Atlas
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a MongoDB Atlas Project&lt;/li&gt;
&lt;li&gt;Create a Database and Collection
The Atlas Database and Collection will be used to store the user and passcode details temporarily.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Realm
&lt;/h3&gt;

&lt;p&gt;Create a Realm Project&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Realm Project will serve as the backend service and performs the following functions&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Receive Request for Passcode (end-point)&lt;/li&gt;
&lt;li&gt;Create a 6 Digit Random Passcode&lt;/li&gt;
&lt;li&gt;Send Acknowledgement to the Application&lt;/li&gt;
&lt;li&gt;Send Passcode to the user email (using Database Trigger)&lt;/li&gt;
&lt;li&gt;Recieve user (email) and Passcode from application (end-point)&lt;/li&gt;
&lt;li&gt;Check and Confirm if Passcode is correct&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Additional Features like setting up time-based expiration (15 mins) is setup using Triggers (time-based)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Realm Endpoints
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Create 2 Endpoints&lt;/strong&gt;&lt;br&gt;
Note: The endpoints are introduced recently and replace the earlier existing feature of webhooks. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the Create Endpoint Option from the left navigation and create the endpoint.&lt;/li&gt;
&lt;li&gt;Select HTTP Method as Post and Response With Result = ON&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v1LQHk8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03r5ua7og7mlsctbm6yp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v1LQHk8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03r5ua7og7mlsctbm6yp.png" alt="Image description" width="880" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One Endpoint is for CreatePasscode and second endpoint is for CheckPasscode&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function: Create 6 Digit Random Passcode&lt;/strong&gt;&lt;br&gt;
This function returns a 6 digit random numeric code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const CreateCode = (min, max) =&amp;gt; {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1) + min); //The maximum is inclusive and the minimum is inclusive
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Function: Create Passcode Function&lt;/strong&gt;&lt;br&gt;
This is the Realm Function linked to the endpoint to create the passcode and send acknowledgement to the application. Please note that in passcode field, we are sending 'xxxxx', as passcode will be sent to the user email and not to the application directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { data, user } = JSON.parse(body.text());

  const code = CreateCode(100000,999999).toString();
  const { v4: uuidv4 } = require('uuid');

  var dbse = await context.services.get("mongodb-atlas").db(db-name).collection(collection-name);

  const trxn = uuidv4().split('-').join('')

  var datx={
    user: data.user, // destination user email
    memo: data.memo, // memo to include in the email
    code: code,
    actv: true,
    trxn: trxn,
    crts: new Date()
  }

  var docx = await dbse.insertOne(datx)

  if (docx) {
    response.setHeader( "Content-Type", "application/json");
    response.setStatusCode(201)
    response.setBody(JSON.stringify({data: {user: data.user, code: 'xxxxxx', trxn: trxn}}));
    return
  }
  else {
    response.setHeader( "Content-Type", "application/json");
    response.setStatusCode(502)
    response.setBody(JSON.stringify({data:{user: data.user, code: 'xxxxxx', trxn: 'xxxxxx'}}));
    return
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Function: Check Passcode Function&lt;/strong&gt;&lt;br&gt;
This is the check the passcode and time validity of the passcode send from the application front-end&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const { data } = JSON.parse(body.text());

  var dbse = await context.services.get("mongodb-atlas").db(db-name).collection(collection-name);

  var docx = await dbse.findOne({ user: data.user, trxn: data.trxn }, {code:1, actv:1});

  if (docx &amp;amp;&amp;amp; docx.code == data.code &amp;amp;&amp;amp; docx.actv)   {
    dbse.updateOne({ user: data.user, trxn: data.trxn }, {'$set': {actv:false}}, {upsert: false});

    response.setHeader( "Content-Type", "application/json");
    response.setStatusCode(200)
    response.setBody(JSON.stringify({auth: true}));
    return
  }
  else   {
    response.setHeader( "Content-Type", "application/json");
    response.setStatusCode(409)
    response.setBody(JSON.stringify({auth: false}));
    return
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Triggers
&lt;/h3&gt;

&lt;p&gt;The triggers are used to increase the applicationscalability and optimize performance. The project utilizes following triggers &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trigger: Send User Email with Passcode&lt;/strong&gt;&lt;br&gt;
This is a Database trigger and it will send an email to the user-email as soon as the code is created and record is inserted into the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1K_nKs64--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqxiqjzbexn5h1cepogz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1K_nKs64--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqxiqjzbexn5h1cepogz.png" alt="Image description" width="880" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Trigger is linked to Realm Function which uses the Nodemailer and GMail for sending email notification to the user with the Passcode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const { user, memo } = JSON.parse(data);

  const nodemailer = require('nodemailer');
  const basemail = context.values.get('basemail')
  const basecode = context.values.get('basecode')
  // the basemail and basecode are setup as Realm Function env variables (values). These are the Gmail Account Email and Password

  const nodemail = nodemailer.createTransport({ service: 'gmail', auth: {user: basemail, pass: basecode} })

  const text = memo.reduce( (a, c) =&amp;gt; a + c.text + '\n\n' , '') 
    + 'Passcode is valid for 15 mins.\n\n'
    + 'Please do not share the Passcode (OTP) with anyone.\n'
    + 'In case you have not initiated this request please contact our helpdesk.\n'
    + '\n\n\n\n' 
    + `Team MongoDB` + '\n' 
    + (new Date()) + '\n\n'
    + '------------------------\n'
    + 'Please do not reply to this email. This email has been generated and sent automatically.\n'
    + 'To ensure that you receive business communications, please add this email to your contact list and address book.\n'

  var mailOptions = {
    from: `OTP Authentication &amp;lt;${(sndr).toLowerCase()}-${basemail}&amp;gt;`,
    replyTo: '',
    to: user,
    subject: head,
    text: text
  }

const mail = await nodemail.sendMail(mailOptions)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Trigger: Reset Passcode after 15 mins&lt;/strong&gt;&lt;br&gt;
This trigger is a time-based trigger which resets the created  passcode after 15 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xv17XfDk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70l77lnox2je7artp54i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xv17XfDk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70l77lnox2je7artp54i.png" alt="Image description" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is triggered every 1 min and checks the database for all  transactions that have created timestamp greater than 15 minutes. If found true, it sets the actv (active) field to false. This is a bulk operation using updateMany&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  var dbse = await context.services.get("mongodb-atlas").db(db-name).collection(collection-name);

  const timx = new Date()
  timx.setMinutes((new Date()).getMinutes() - 15);
  // return ({'new': (new Date()).toISOString(), 'old': (new Date(timx)).toISOString()})

  const docx = await dbse.updateMany({ actv: true, crts: {'$lte': timx} }, {'$set': {actv:false}}, {upsert: false});
  console.log (`reset count: ${docx.modifiedCount}`)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;In Summary, we have used&lt;br&gt;
MongoDB Atlas, MongoDB Realm Functions and MongoDB Realm Triggers with minimal external libraries to create an authentication service. This removes dependence on third party applications and overall setup time is approx 20-30 mins. &lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;The usermail and passcode should be further secured in the database by using crypto hash functions. MongoDB Realm has native support for NodeJS Crypto Module. &lt;/p&gt;

&lt;p&gt;The same is also to be implemented on the browser / application side when sending the payload for Passcode verification. &lt;/p&gt;

&lt;p&gt;This has been skipped here to allow showing the details of the functions / code.&lt;/p&gt;

&lt;p&gt;Thank You for reading and I hope this is helpful during your application development.  &lt;/p&gt;

&lt;p&gt;I look forward to your comments and feedback.&lt;/p&gt;

</description>
      <category>atlashackathon</category>
    </item>
  </channel>
</rss>
