{"componentChunkName":"component---src-templates-tag-js","path":"/tags/api/","result":{"data":{"site":{"siteMetadata":{"title":"LoginRadius Blog"}},"allMarkdownRemark":{"totalCount":10,"edges":[{"node":{"fields":{"slug":"/identity/mfa-vs-rba/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>With rising cyber threats, organizations need strong authentication to safeguard sensitive data and user accounts. Multi-Factor Authentication (MFA) adds extra verification layers, while Risk-Based Authentication (RBA) adapts security based on user behavior.</p>\n<p>Both play a crucial role in preventing unauthorized access and reducing security risks. In this blog, we’ll explore what they are, how they work, and why they matter for your security.</p>\n<h2 id=\"what-is-multi-factor-authentication\" style=\"position:relative;\"><a href=\"#what-is-multi-factor-authentication\" aria-label=\"what is multi factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Multi-Factor Authentication?</h2>\n<p><a href=\"https://www.loginradius.com/blog/identity/what-is-multi-factor-authentication/\">Multi-factor authentication (MFA)</a> is a security measure that requires users to provide multiple forms of verification before gaining access to a system. Instead of relying solely on passwords, MFA security uses a combination of authentication factors to strengthen security and prevent unauthorized access.</p>\n<h2 id=\"types-of-authentication-factors\" style=\"position:relative;\"><a href=\"#types-of-authentication-factors\" aria-label=\"types of authentication factors permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Types of Authentication Factors</h2>\n<p>MFA typically involves three categories of authentication factors:</p>\n<ol>\n<li><strong>Something You Know</strong> – Passwords, PINs, or security questions.    </li>\n<li><strong>Something You Have</strong> – Smart cards, authentication tokens, or mobile authentication apps.    </li>\n<li><strong>Something You Are</strong> – Biometric verification like fingerprints, facial recognition, or iris scans.</li>\n</ol>\n<p>By combining these factors, multi-layer authentication ensures that even if one factor is compromised, the account remains secure.</p>\n<h2 id=\"benefits-of-multi-factor-authentication\" style=\"position:relative;\"><a href=\"#benefits-of-multi-factor-authentication\" aria-label=\"benefits of multi factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Benefits of Multi-Factor Authentication</h2>\n<h3 id=\"1-enhanced-security\" style=\"position:relative;\"><a href=\"#1-enhanced-security\" aria-label=\"1 enhanced security permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. Enhanced Security</h3>\n<p>Multi-factor authentication in cyber security significantly reduces the risk of account breaches by adding multiple layers of protection beyond just passwords.</p>\n<h3 id=\"2-protection-against-credential-theft\" style=\"position:relative;\"><a href=\"#2-protection-against-credential-theft\" aria-label=\"2 protection against credential theft permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Protection Against Credential Theft</h3>\n<p>Since MFA security requires more than one authentication factor, stolen passwords alone cannot grant attackers access to accounts.</p>\n<h3 id=\"3-regulatory-compliance\" style=\"position:relative;\"><a href=\"#3-regulatory-compliance\" aria-label=\"3 regulatory compliance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. Regulatory Compliance</h3>\n<p>Many industries require MFA for compliance with security regulations such as GDPR, HIPAA, and PCI-DSS, ensuring adherence to data protection standards.</p>\n<h3 id=\"4-reduced-risk-of-phishing-attacks\" style=\"position:relative;\"><a href=\"#4-reduced-risk-of-phishing-attacks\" aria-label=\"4 reduced risk of phishing attacks permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. Reduced Risk of Phishing Attacks</h3>\n<p>Phishing attacks often rely on stealing login credentials, but with MFA security in place, attackers would need access to an additional factor, making unauthorized access significantly more difficult.</p>\n<p>Protect every login! Uncover <a href=\"https://www.loginradius.com/blog/identity/benefits-of-mfa/\">the benefits of MFA</a>.</p>\n<h3 id=\"5-improved-user-trust-and-confidence\" style=\"position:relative;\"><a href=\"#5-improved-user-trust-and-confidence\" aria-label=\"5 improved user trust and confidence permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>5. Improved User Trust and Confidence</h3>\n<p>When organizations implement strong authentication mechanisms, users feel more secure knowing their data is well-protected. This fosters trust in digital services and platforms.</p>\n<p>By requiring multiple authentication factors, MFA enhances identity risk management, reducing vulnerabilities related to credential-based attacks.</p>\n<h2 id=\"what-is-risk-based-authentication\" style=\"position:relative;\"><a href=\"#what-is-risk-based-authentication\" aria-label=\"what is risk based authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Risk-Based Authentication?</h2>\n<p>Risk-based authentication (RBA), also known as <a href=\"https://www.loginradius.com/products/adaptive-mfa\">adaptive authentication</a>, is a dynamic security approach that evaluates user behavior and contextual factors before granting access. Instead of applying uniform authentication policies, risk-based security adjusts authentication requirements based on perceived risk levels.</p>\n<h2 id=\"how-risk-based-authentication-works\" style=\"position:relative;\"><a href=\"#how-risk-based-authentication-works\" aria-label=\"how risk based authentication works permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How Risk-Based Authentication Works?</h2>\n<ol>\n<li><strong>Behavioral Analysis</strong> – Identifies normal user behavior patterns to detect anomalies.    </li>\n<li><strong>Device Recognition</strong> – Ensures access only from known and trusted devices.    </li>\n<li><strong>IP Address &#x26; Geolocation Monitoring</strong> – Flags login attempts from unusual locations.    </li>\n<li><strong>Time-Based Access Control</strong> – Monitors login times to detect suspicious activities.    </li>\n<li><strong>Real-Time Risk Evaluation</strong> – Uses AI-driven analytics to assess risk dynamically.</li>\n</ol>\n<p><img src=\"/5081309ed356e5e32a6454cd316bc45d/adaptive-mfa.webp\" alt=\"Risk-based Authentication\"></p>\n<h2 id=\"benefits-of-risk-based-multi-factor-authentication\" style=\"position:relative;\"><a href=\"#benefits-of-risk-based-multi-factor-authentication\" aria-label=\"benefits of risk based multi factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Benefits of Risk-Based Multi-Factor Authentication</h2>\n<h3 id=\"better-user-experience-with-heightened-security\" style=\"position:relative;\"><a href=\"#better-user-experience-with-heightened-security\" aria-label=\"better user experience with heightened security permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Better User Experience with Heightened Security</h3>\n<p>Risk-based MFA makes it easier for users. Low-risk users can log in smoothly. High-risk access attempts need extra authentication steps. This balance between security and convenience enhances overall efficiency.</p>\n<h3 id=\"more-robust-defense-against-fraud\" style=\"position:relative;\"><a href=\"#more-robust-defense-against-fraud\" aria-label=\"more robust defense against fraud permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>More Robust Defense Against Fraud</h3>\n<p>By analyzing login behaviors, device information, and geographical location, risk authentication detects suspicious activities and prevents fraudulent access attempts. It effectively minimizes risks related to identity theft and account takeovers.</p>\n<h3 id=\"regulatory-compliance\" style=\"position:relative;\"><a href=\"#regulatory-compliance\" aria-label=\"regulatory compliance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Regulatory Compliance</h3>\n<p>Organizations leveraging risk-based authentication ensure compliance with stringent security regulations like the GDPR and CCPA by implementing advanced identity risk management. This helps in meeting legal and industry-specific security requirements.</p>\n<p>Failing to comply with GDPR can lead to security breaches, damage your brand's reputation, and result in hefty fines! <a href=\"https://www.loginradius.com/resource/ebook/loginradius-gdpr-compliance/\">Learn more.</a></p>\n<h3 id=\"cost-effective-security-implementation\" style=\"position:relative;\"><a href=\"#cost-effective-security-implementation\" aria-label=\"cost effective security implementation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cost-Effective Security Implementation</h3>\n<p>Unlike static security measures, risk-based authentication optimizes authentication requirements based on risk assessment, reducing unnecessary authentication steps and streamlining security processes without increasing operational costs.</p>\n<h3 id=\"increased-adaptability-to-emerging-threats\" style=\"position:relative;\"><a href=\"#increased-adaptability-to-emerging-threats\" aria-label=\"increased adaptability to emerging threats permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Increased Adaptability to Emerging Threats</h3>\n<p>With cyber threats constantly evolving, risk-based MFA ensures security policies remain dynamic. Organizations can adjust authentication requirements based on new threat patterns and user behaviors.</p>\n<p>Want a detailed guide on risk-based authentication? Download this insightful guide:</p>\n<p><a href=\"https://www.loginradius.com/resource/guide/enterprise-risk-based-authentication/\"><img src=\"/99ee0fac455a7e68c4148398be3b2de8/an-enterprises-guide-to-risk-based-authentication.webp\" alt=\"an enterprises guide to risk based authentication\"></a></p>\n<h2 id=\"risk-based-vs-traditional-mfa\" style=\"position:relative;\"><a href=\"#risk-based-vs-traditional-mfa\" aria-label=\"risk based vs traditional mfa permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Risk-based vs Traditional MFA</h2>\n<table>\n<thead>\n<tr>\n<th><strong>Factor</strong></th>\n<th><strong>Risk-Based Authentication (RBA)</strong></th>\n<th><strong>Traditional Multi-Factor Authentication (MFA)</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Authentication Approach</strong></td>\n<td>Adapts security measures based on user behavior and risk levels</td>\n<td>Requires a fixed set of authentication steps for every login</td>\n</tr>\n<tr>\n<td><strong>User Experience</strong></td>\n<td>Seamless, prompts MFA only when risk is detected</td>\n<td>Requires MFA for every login, which can be cumbersome</td>\n</tr>\n<tr>\n<td><strong>Security Level</strong></td>\n<td>Dynamic security based on real-time risk analysis</td>\n<td>Static security, same for all users regardless of risk</td>\n</tr>\n<tr>\n<td><strong>Risk Assessment</strong></td>\n<td>Considers factors like location, device, IP, and login patterns</td>\n<td>No contextual awareness, applies the same process to all users</td>\n</tr>\n<tr>\n<td><strong>Efficiency</strong></td>\n<td>Reduces friction for low-risk users while securing high-risk attempts</td>\n<td>Increases login friction for all users equally</td>\n</tr>\n<tr>\n<td><strong>Best Use Cases</strong></td>\n<td>Enterprises needing adaptive security with minimal disruption</td>\n<td>Organizations requiring uniform authentication enforcement</td>\n</tr>\n<tr>\n<td><strong>Implementation Complexity</strong></td>\n<td>Requires AI/ML-driven risk assessment and continuous monitoring</td>\n<td>Easier to implement with standard authentication methods</td>\n</tr>\n<tr>\n<td><strong>Compliance &#x26; Security</strong></td>\n<td>Helps meet compliance with intelligent access controls</td>\n<td>Meets compliance but can add unnecessary friction</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"risk-based-mfa-examples\" style=\"position:relative;\"><a href=\"#risk-based-mfa-examples\" aria-label=\"risk based mfa examples permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Risk-Based MFA Examples</h2>\n<p>Risk-based MFA is widely used across various industries to enhance security while maintaining user convenience. For example, banking institutions employ risk-based authentication by analyzing user behavior, transaction location and history.</p>\n<p>E-commerce platforms use risk-based MFA to keep customer accounts safe. They watch buying patterns to identify fraudulent purchases.</p>\n<p>Similarly, corporate IT systems also leverage risk-based security to enforce strict authentication policies for high-risk access requests while allowing seamless logins for trusted employees.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>Implementing advanced security measures like multi-factor authentication and risk-based authentication is crucial in today’s modern digital landscape.</p>\n<p>Multi-factor authentication enhances security by requiring multiple verification methods, while risk-based MFA dynamically assesses risk to provide a seamless yet secure user experience. Organizations that leverage these technologies benefit from stronger identity protection, compliance adherence, and improved cybersecurity resilience.</p>\n<p>If you wish to reinforce your security by leveraging cutting edge MFA and risk-based auth, <a href=\"https://www.loginradius.com/contact-us?utm_source=blog&#x26;utm_medium=web&#x26;utm_campaign=mfa-vs-rba\">reach us for a quick demo.</a></p>\n<h2 id=\"faqs\" style=\"position:relative;\"><a href=\"#faqs\" aria-label=\"faqs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>FAQs</h2>\n<p><strong>How Does One Implement Risk-Based Authentication?</strong></p>\n<p>Organizations implement RBA by using AI-driven tools like <a href=\"https://www.loginradius.com/products/adaptive-mfa\">LoginRadius</a> that analyze user behavior, device, and location data to assess risk and enforce adaptive authentication.</p>\n<p><strong>How to Enable Multi-Factor Authentication?</strong></p>\n<p>MFA can be enabled by integrating it into an organization's security framework through an identity provider, requiring users to verify identity through multiple authentication factors.</p>\n<p><strong>What is Adaptive Multi-Factor Authentication?</strong></p>\n<p>Adaptive MFA/ risk-based MFA dynamically adjusts authentication requirements based on real-time risk assessment, ensuring a secure yet seamless user experience.</p>\n<p><strong>How Does Multi-Factor Authentication Make a System More Secure?</strong></p>\n<p>MFA enhances security by requiring multiple authentication factors, making it harder for attackers to gain unauthorized access even if one factor is compromised.</p>\n<p><strong>How Does Risk-Based MFA Differ from Traditional MFA?</strong></p>\n<p>Traditional MFA uses set authentication steps. Risk-based MFA changes how we authenticate users. It does this by looking at user behavior and risk. Multi-factor authentication (MFA) is a way to improve security. It requires users to give more than one form of verification to access a system.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"February 27, 2025","updated_date":null,"title":"Risk-Based Authentication vs. MFA: Key Differences Explained","tags":["API","Identity Management","User Authentication","CIAM Security"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/edcd19470ad543ebda9bf1653aa68f74/58556/banner.webp","srcSet":"/static/edcd19470ad543ebda9bf1653aa68f74/61e93/banner.webp 200w,\n/static/edcd19470ad543ebda9bf1653aa68f74/1f5c5/banner.webp 400w,\n/static/edcd19470ad543ebda9bf1653aa68f74/58556/banner.webp 800w,\n/static/edcd19470ad543ebda9bf1653aa68f74/99238/banner.webp 1200w,\n/static/edcd19470ad543ebda9bf1653aa68f74/7c22d/banner.webp 1600w,\n/static/edcd19470ad543ebda9bf1653aa68f74/04b61/banner.webp 6251w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},{"node":{"fields":{"slug":"/identity/developer-first-identity-provider-loginradius/"},"html":"<p>Identity is evolving, and developers are at the forefront of this transformation. Every day brings a new learning—adapting to new standards and refining approaches to building secure, seamless experiences.</p>\n<p>We’re here to support developers on that journey. We know how important simplicity, efficiency, and well-structured documentation are when working with identity and access management solutions. That’s why we’ve redesigned the <a href=\"https://www.loginradius.com/\">LoginRadius website</a>—to be faster, more intuitive, and developer-first in every way.</p>\n<p>The goal? Having them spend less time searching and more time building.</p>\n<h2 id=\"whats-new-and-improved-on-the-loginradius-website\" style=\"position:relative;\"><a href=\"#whats-new-and-improved-on-the-loginradius-website\" aria-label=\"whats new and improved on the loginradius website permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What’s New and Improved on the LoginRadius Website?</h2>\n<p>LoginRadius’ vision is to give developers a product that simplifies identity management so they can focus on building, deploying, and scaling their applications. To enhance this experience, we’ve spent the last few months redesigning our interface— making navigation more intuitive and reassuring that essential resources are easily accessible.</p>\n<p>Here’s a closer look at what’s new and why it’s important:</p>\n<h3 id=\"a-developer-friendly-dark-theme\" style=\"position:relative;\"><a href=\"#a-developer-friendly-dark-theme\" aria-label=\"a developer friendly dark theme permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A Developer-Friendly Dark Theme</h3>\n<p><img src=\"/f46881583c7518a93bb24e94c32320de/a-developer-friendly-dark-theme.webp\" alt=\"This image shows how LoginRadius offers several authentication methods like traditional login, social login, passwordless login, passkeys and more in a dark mode.\">    </p>\n<p>Developers spend long hours working in dark-themed IDEs and terminals, so we’ve designed the LoginRadius experience to be developer-friendly and align with that preference.</p>\n<p>The new dark mode reduces eye strain, enhances readability, and provides a seamless transition between a coding environment and our platform. Our new design features a clean, modern aesthetic with a consistent color scheme and Barlow typography, ensuring better readability. High-quality graphics and icons are thoughtfully placed to enhance the content without adding visual clutter.</p>\n<p>So, whether you’re navigating our API docs or configuring authentication into your system, our improved interface will make those extended development hours more comfortable and efficient.</p>\n<h3 id=\"clear-categorization-for-loginradius-capabilities\" style=\"position:relative;\"><a href=\"#clear-categorization-for-loginradius-capabilities\" aria-label=\"clear categorization for loginradius capabilities permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Clear Categorization for LoginRadius Capabilities</h3>\n<p><img src=\"/e5358b82be414940f3fb146013845933/capabilities.webp\" alt=\"This image shows a breakdown of all the LoginRadius CIAM capabilities, including authentication, security, UX, scalability and multi-brand management.\"></p>\n<p>We’ve restructured our website to provide a straightforward breakdown of our customer identity and access management platform capabilities, helping you quickly find what you need:</p>\n<ul>\n<li>Authentication: Easily understand <a href=\"https://www.loginradius.com/blog/identity/authentication-option-for-your-product/\">how to choose the right login method</a>, from traditional passwords and OTPs to social login, federated SSO, and passkeys with few lines of code.</li>\n<li>Security: Implement no-code security features like bot detection, IP throttling, breached password alerts, DDoS protection, and adaptive MFA to safeguard user accounts.</li>\n<li>User Experience: Leverage AI builder, hosted pages, and drag-and-drop workflows to create smooth, branded sign-up and login experiences.</li>\n<li>High Performance &#x26; Scalability: Confidently scale with sub-100ms API response times, 100% uptime, 240K+ RPS, and 28+ global data center regions.</li>\n<li>Multi-Brand Management: Efficiently manage multiple identity apps, choosing isolated or shared data stores based on your brand’s unique needs.</li>\n</ul>\n<p>This structured layout ensures you can quickly understand each capability and how it integrates into your identity ecosystem.</p>\n<h3 id=\"developer-first-navigation\" style=\"position:relative;\"><a href=\"#developer-first-navigation\" aria-label=\"developer first navigation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Developer-First Navigation</h3>\n<p><img src=\"/a8c155c2b6faf3d5f4b4de4e2b14d763/developers-menu.webp\" alt=\"This image shows the LoginRadius menu bar, highlighting the developer dropdown.\">   </p>\n<p>We’ve been analyzing developer workflows to identify how you access key resources. That’s why we redesigned our navigation with one goal in mind: to reduce clicks and make essential resources readily available.</p>\n<p>The new LoginRadius structure puts APIs, SDKs, and integration guides right at the menu bar under the Developers dropdown so you can get started faster. Our Products, Solutions, and Customer Services are also clearly categorized, helping development teams quickly find the right tools and make informed decisions.</p>\n<h3 id=\"quick-understanding-of-integration-benefits\" style=\"position:relative;\"><a href=\"#quick-understanding-of-integration-benefits\" aria-label=\"quick understanding of integration benefits permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Quick Understanding of Integration Benefits</h3>\n<p><img src=\"/b2f9a964a2da0ea83e2f8596b833bba7/we-support-your-tech-stack.webp\" alt=\"This image shows a list of popular programming languages and frameworks offered by LoginRadius.\"></p>\n<p>Developers now have a clear view of the tech stack available with LoginRadius, designed to support diverse business needs.</p>\n<p>Our platform offers pre-built SDKs for Node.js, Python, Java, and more, making CIAM integration seamless across popular programming languages and frameworks.</p>\n<h2 id=\"over-to-you-now\" style=\"position:relative;\"><a href=\"#over-to-you-now\" aria-label=\"over to you now permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Over to You Now!</h2>\n<p>Check out our <a href=\"https://www.loginradius.com/\">revamped LoginRadius website</a> and see how the improved experience makes it easier to build, scale, and secure your applications.</p>\n<p>Do not forget to explore the improved navigation and API documentation, and get started with our free trial today. We’re excited to see what you’ll build with LoginRadius!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"February 21, 2025","updated_date":null,"title":"Revamped & Ready: Introducing the New Developer-First LoginRadius Website","tags":["Developer tools","API","Identity Management","User Authentication"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7857142857142858,"src":"/static/80b4e4fbe176a10a327d273504607f32/58556/hero-section.webp","srcSet":"/static/80b4e4fbe176a10a327d273504607f32/61e93/hero-section.webp 200w,\n/static/80b4e4fbe176a10a327d273504607f32/1f5c5/hero-section.webp 400w,\n/static/80b4e4fbe176a10a327d273504607f32/58556/hero-section.webp 800w,\n/static/80b4e4fbe176a10a327d273504607f32/99238/hero-section.webp 1200w,\n/static/80b4e4fbe176a10a327d273504607f32/7c22d/hero-section.webp 1600w,\n/static/80b4e4fbe176a10a327d273504607f32/1258b/hero-section.webp 2732w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Rakesh Soni","github":"oyesoni","avatar":"rakesh-soni.webp"}}}},{"node":{"fields":{"slug":"/engineering/why-we-rebuilt-loginradius-dot-net-core-apis-with-go/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>Currently, the LoginRadius Identity Platform processes more than 100K requests per second. As our developer and enterprise customers grow, we should be able to scale our APIs to handle staggering loads of requests per second. It won’t be surprising if our APIs have to serve a million requests per second in the future.</p>\n<p>Generally, we add more instances, CPU, or memory for supporting high request volumes. However, it has been burdening our infrastructure budget and maintenance. </p>\n<p>So, we’re focused on reducing the cost of compute capacity by improving efficiency. In this engineering update, we share our experience with a highly effective, low-risk, large-scale performance and cost optimization with Go.</p>\n<p>LoginRadius production environment consists of 30+ microservices backed by a cloud-native infrastructure. Most of these services are written in .NET and Node.js. In Q1 2021, we explored the possibilities of improving the performance of our services and optimizing costs.</p>\n<h2 id=\"how-loginradius-has-been-handling-high-rps-throughput\" style=\"position:relative;\"><a href=\"#how-loginradius-has-been-handling-high-rps-throughput\" aria-label=\"how loginradius has been handling high rps throughput permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How LoginRadius Has Been Handling High RPS Throughput?</h2>\n<p>LoginRadius tech stack consists of 30+ microservices. We have different microservices for each business service like Authentication, Web SSO, Federated SSO, etc. </p>\n<ul>\n<li>We have developed application microservices in various languages per the prevailing microservice use case.</li>\n<li>We have deployed our application in a multi-cloud environment across AWS, Azure, and Google Cloud by leveraging multiple availability zones and regions.</li>\n</ul>\n<h3 id=\"1-architecture\" style=\"position:relative;\"><a href=\"#1-architecture\" aria-label=\"1 architecture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Architecture</h3>\n<p><strong>Core Applications:</strong> Multiple microservices instances for Authentication, Account API, Analytics API, Risk-based Authentication, Backend Jobs, Integrations, and much more, </p>\n<p><strong>Data Storage:</strong> MongoDB, Elasticsearch, Redis, and PostgreSQL clusters are used to store a range of datasets for various applications and functionalities.</p>\n<p><strong>Queues:</strong> Amazon Kinesis Data Streams, Amazon Simple Notification Service (SNS), Amazon Simple Queue Service (SQS), and Azure Queue Storage. </p>\n<p><strong>Other Services:</strong> Services for rate-limiting, bcrypt clusters, feature flags, and more.</p>\n<p><strong>Routing:</strong> AWS load balancers (ALB, NLB, and ELB from AWS) and some nodes running NGINX as a proxy.</p>\n<h3 id=\"2-availability\" style=\"position:relative;\"><a href=\"#2-availability\" aria-label=\"2 availability permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Availability</h3>\n<p>We've been utilizing a multi-cloud and multi-region architecture for years based on our and our customers’ data and privacy compliance requirements. However, as our usage (and load) grew with maintenance costs, we relied more on AWS resources.</p>\n<ul>\n<li>We are using multiple regions and multiple availability zones as per region.</li>\n<li>We are using terraform scripts to provision new environments. This infrastructure automation allowed us to quickly scale from thousands of requests per second to hundreds of thousands of requests per second.  </li>\n</ul>\n<p>This is the basic architecture of the environment in the US:</p>\n<p><img src=\"/491e73fe4836ca5daa93f6aad47f3b4d/basic-architecture.webp\" alt=\"Basic Architecture - US\"></p>\n<p>Each request is processed as follows:</p>\n<p><img src=\"/fc6929115da8e289aaaaa4880d05fe5b/request-processing-flow.webp\" alt=\"Request Processing Flow\"></p>\n<p>The above diagram shows two cloud regions — US East and US West.</p>\n<p>When requests come:</p>\n<ul>\n<li>First, our infrastructure checks the primary region's health. If health is good, all requests are served by the primary US East region with three separate availability zones. </li>\n<li>If health checks fail for the primary region, the US West region serves all the requests with three separate availability zones.</li>\n</ul>\n<p><strong>So, how do we maintain high availability?</strong></p>\n<p>Every availability zone has operating instances of all services (including databases). If one availability zone is down, we still have two availability zones.</p>\n<h3 id=\"3-scaling\" style=\"position:relative;\"><a href=\"#3-scaling\" aria-label=\"3 scaling permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Scaling</h3>\n<p>We are using a two-pronged scaling approach as scaling based on resource utilization (CPU &#x26; Memory) alone is not practical.</p>\n<ol>\n<li>Traffic-based scaling</li>\n<li>Based on CPU &#x26; Memory utilization</li>\n</ol>\n<h4 id=\"why-scaling-was-challenging\" style=\"position:relative;\"><a href=\"#why-scaling-was-challenging\" aria-label=\"why scaling was challenging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Scaling Was Challenging?</h4>\n<p>Once, our multi-tenant application received a sudden spike in API requests — from thousands of requests to millions. Usually, adding new infrastructure to the existing pool takes around 60 seconds. And application deployment and start-up time were about 90 seconds. Plus, considering other possible delays in scaling, we can lose about 5 minutes for scaling up.</p>\n<p>Further, adding the time to gather metrics and make the scaling decision, the total delay can be ~6 minutes. This process can impact all multi-tenant customers' critical applications because user authentication and authorization are essential.</p>\n<p>We keep <em>Scaling Buffers</em> to support this kind of scenario.</p>\n<blockquote>\n<p><strong>Scaling Buffers:</strong>  During the <em>Scale-up Time</em>, the <em>Scaling Buffer</em> is the service's highest predicted traffic spike. Depending on the scaling strategy, we store several types of the buffer.</p>\n</blockquote>\n<p>Usually, we set a one million requests concurrency buffer. And based on the traffic pattern, our scaling automation triggers the scaling.</p>\n<h2 id=\"why-our-platform-performance-was-good-but-not-great\" style=\"position:relative;\"><a href=\"#why-our-platform-performance-was-good-but-not-great\" aria-label=\"why our platform performance was good but not great permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Our Platform Performance Was Good, But Not Great?</h2>\n<p>Our Platform performance is good. We can quickly handle millions of requests, and our application platform was scalable but not great. Minding the kind of growth we’re expecting, we wanted to improve and prepare our platform for the future.</p>\n<h3 id=\"challenges-in-the-existing-platform\" style=\"position:relative;\"><a href=\"#challenges-in-the-existing-platform\" aria-label=\"challenges in the existing platform permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Challenges in the Existing Platform</h3>\n<h4 id=\"1-startup-time\" style=\"position:relative;\"><a href=\"#1-startup-time\" aria-label=\"1 startup time permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Startup Time</h4>\n<p>No. of requests can fluctuate within a few seconds if not minutes or hours, especially with specific events such as holiday shopping, promotional events, Black Friday, etc. So, in the event of traffic spikes, application startup time plays a significant role in scaling.</p>\n<p>Our application startup time was around 90 seconds, so whenever scaling was happening due to high traffic, scaling took more time. That's why we needed to improve the application startup time.</p>\n<h4 id=\"2-cost\" style=\"position:relative;\"><a href=\"#2-cost\" aria-label=\"2 cost permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Cost</h4>\n<p>We used hundreds of <em>AWS c5.2xlarge</em> instances in a production environment to handle daily traffic. During certain events such as holiday shopping and Black Friday, we doubled our infrastructure according to expected traffic with a 20~30% buffer. We kept a high buffer because scaling took time with the existing .NET Core services. As a result, infrastructure cost was burdening as we were inefficiently deploying cloud infrastructure.</p>\n<h4 id=\"3-lack-of-flexibility-and-customization\" style=\"position:relative;\"><a href=\"#3-lack-of-flexibility-and-customization\" aria-label=\"3 lack of flexibility and customization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Lack of Flexibility and Customization</h4>\n<p>We designed our Identity Platform a few years ago. Since then, the technology landscape has dramatically improved and optimized in recent years. </p>\n<p>Also, current technology platforms available to build and support our product (Identity Platform) are limited. So, it is crucial to align functionality with proper technology capabilities.</p>\n<p>We were facing challenges in customization. It was inflexible and limiting to deliver the required outcomes in more complex situations and use cases.</p>\n<h2 id=\"the-road-to-lightning-performance-thanks-to-go\" style=\"position:relative;\"><a href=\"#the-road-to-lightning-performance-thanks-to-go\" aria-label=\"the road to lightning performance thanks to go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Road to Lightning Performance, Thanks to Go</h2>\n<h3 id=\"why-go\" style=\"position:relative;\"><a href=\"#why-go\" aria-label=\"why go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why <em>Go</em>?</h3>\n<p>We did a lot of research to choose the appropriate programming language for our application. We needed a language that would be simple to understand and learn, easy to maintain, and has high concurrency. Our research ended with Go due to its amazing qualities.</p>\n<p>Let's take a closer look. <em>Why choose Go? What makes Go such an excellent development language? What distinguishes it from the competition?</em> </p>\n<p>Let's get to the bottom of this by looking at what makes Go special.</p>\n<h3 id=\"go--background\" style=\"position:relative;\"><a href=\"#go--background\" aria-label=\"go  background permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Go — Background</h3>\n<p>Go is an open-source programming language developed by Google's Rob Pike, Robert Griesemer, and Ken Thompson. It was initially released in 2009. It has several enhancements and additions based on the C syntax to properly control memory use, manage objects, and enable static or strict typing along with concurrency.</p>\n<h4 id=\"1-concurrency\" style=\"position:relative;\"><a href=\"#1-concurrency\" aria-label=\"1 concurrency permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Concurrency</h4>\n<p>Concurrent code can be executed in parallel by separate computer cores or in sequence. Most programming languages lack concurrent execution when working with multiple threads. They often slow down programming, compiling, and execution.</p>\n<p>Go works with goroutines that are lightweight, low-cost threads. And Go channels allow goroutines to communicate with one another. </p>\n<p>Sequential Processes Communication: They are very similar to threads in Java but lightweight, and the cost of creating them is meager.</p>\n<h4 id=\"2-performance\" style=\"position:relative;\"><a href=\"#2-performance\" aria-label=\"2 performance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Performance</h4>\n<p>Go's core value is simplicity: it builds quickly, runs quickly, and is simple to learn. To help speed things up, there are no classes or type inheritance. This makes it easier to build a market-ready product quickly. Furthermore, its simplicity allows for quick and simple maintenance.</p>\n<h4 id=\"3-standard-library\" style=\"position:relative;\"><a href=\"#3-standard-library\" aria-label=\"3 standard library permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Standard Library</h4>\n<p>Go has an excellent standard library that includes a large number of built-in essential type functions and packages that are both practical and straightforward to use: I/O, encoding and decoding, manipulating raw bytes, network utility functions, parsing, debugging, and a lot more are all made simple by particular packages. Testing support is also included in the standard library, so no other dependencies are required.</p>\n<h4 id=\"4-easy-to-learn\" style=\"position:relative;\"><a href=\"#4-easy-to-learn\" aria-label=\"4 easy to learn permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4) Easy to Learn</h4>\n<p>Go has a simpler syntax than other languages and is simple to learn. The syntax of Go is somewhat similar to the C language. Developers can begin with Go in a couple of hours, but they need to spend time understanding best coding practices, especially understanding goroutines for concurrency.</p>\n<h2 id=\"benchmarking-api-performance-gains\" style=\"position:relative;\"><a href=\"#benchmarking-api-performance-gains\" aria-label=\"benchmarking api performance gains permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Benchmarking API Performance Gains</h2>\n<p>We run benchmarks on our API so that the performance insights help us make decisions about the tech stack. It will paint a clearer picture of where we stand compared to our existing tech stack and what areas need improvement or immediate attention. </p>\n<p>We did multiple stress tests on our high usage APIs built separately with .NET Core(Old) and Go (new). </p>\n<p>We are using Kubernetes to deploy and manage our microservices and application infrastructure and deploy our application microservices across multiple Pods.</p>\n<h3 id=\"stress-test-scenario\" style=\"position:relative;\"><a href=\"#stress-test-scenario\" aria-label=\"stress test scenario permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stress Test Scenario</h3>\n<table>\n<thead>\n<tr>\n<th>Test Item</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Instance Type</td>\n<td>c5.2xlarge on AWS</td>\n</tr>\n<tr>\n<td>No. of Instances</td>\n<td>20</td>\n</tr>\n<tr>\n<td>Reverse Proxy</td>\n<td>NGINX</td>\n</tr>\n<tr>\n<td>Concurrent Requests</td>\n<td>20K per second</td>\n</tr>\n<tr>\n<td>Duration</td>\n<td>5 minutes</td>\n</tr>\n<tr>\n<td>Stress Test Tool</td>\n<td><a href=\"https://gatling.io/\">Gatling</a></td>\n</tr>\n</tbody>\n</table>\n<p>We deployed both applications in the same infrastructure and did the same stress test.\nGolang application has performed much better.</p>\n<h4 id=\"existing-application-matrix--net-core\" style=\"position:relative;\"><a href=\"#existing-application-matrix--net-core\" aria-label=\"existing application matrix  net core permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Existing Application Matrix — .NET Core</h4>\n<figure align=\"center\">\n  <img src=\"/425ce0aea8c01e3281101dd268d0def6/requests-and-responses-per-second-dot-net-core.webp\" alt=\"Requests and Responses per Second (.NET Core)\">\n  <figcaption> Graph - 1(a): Requests and Responses per Second (.NET Core)</figcaption>\n</figure>\n \n<figure align=\"center\">\n  <img src=\"/d7b965865c218de9b3e71b6559787500/response-time-percentiles-dot-net-core.webp\" alt=\"API Response Time (.NET Core)\">\n  <figcaption> Graph -1(b): API Response Time (.NET Core)</figcaption>\n</figure>\n<figure align=\"center\">\n  <img src=\"/cd1c01d04ed3965ac3ca5bfce7ba66dc/overall-matrix-dot-net-core.webp\" alt=\"Overall Matrix (.NET Core)\">\n  <figcaption> Graph - 1(c): Overall Matrix (.NET Core)</figcaption>\n</figure>\n<p>You can see some errors in Graph - 1(a) after ramping up to 15K users. Also, response time is increasing, as seen in Graph - 1(b).</p>\n<p>The application can recover after a couple of seconds, and after that, the application cannot respond. Application scaling is taking time. And existing infra cannot handle this spike, so the application crashes after 18K RPS.</p>\n<h4 id=\"new-application-matrix--go\" style=\"position:relative;\"><a href=\"#new-application-matrix--go\" aria-label=\"new application matrix  go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>New Application Matrix — Go</h4>\n<p>We did the same stress test with the new Go application. It is easily able to handle this kind of concurrency without any issue. </p>\n<figure align=\"center\">\n  <img src=\"/64fd50adc421658ca67fbf096038dc9e/requests-and-responses-per-second-go-lang.webp\" alt=\"Requests and Responses per Second (Go)\">\n  <figcaption> Graph - 2(a): Requests and Responses per Second (Go)</figcaption>\n</figure>\n \n<figure align=\"center\">\n  <img src=\"/dd50184c7b2f042915816c6374a53590/response-time-percentiles-go-lang.webp\" alt=\"API Response Time (Go)\">\n  <figcaption> Graph -2(b): API Response Time (Go)</figcaption>\n</figure>\n<figure align=\"center\">\n  <img src=\"/19f6d7a35332ce026578459805a2327d/overall-matrix-go-lang.webp\" alt=\"Overall Matrix (Go)\">\n  <figcaption> Graph - 2(c): Overall Matrix (Go)</figcaption>\n</figure>\n<p>The Go application can easily handle 20K ramp-up requests per second without any issue, as shown in Graph -2(a).</p>\n<p>You can see in Graph - 2(b) what the response time was after 2 min 47 sec for a couple of seconds. The Go application was scaling during that time. It is scaling quickly, so it is not impacting API request performance, and, also, the application can recover response API time as expected. </p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this article, you have learned how we have achieved better API performance by rebuilding them in Go, which were previously built in .NET Core. And you have understood our approach to this transition and how it increased the API performance of the LoginRadius Identity Platform.</p>\n<p>Leverage LoginRadius Identity Platform to build authentication functionality for your web and mobile apps. <a href=\"https://accounts.loginradius.com/auth.aspx?action=register\">Sign up for a free LoginRadius account here</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"June 06, 2022","updated_date":null,"title":"Why We Re-engineered LoginRadius APIs with Go?","tags":["Go","API",".NET","LoginRadius"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/da26686e342d94b3007681cd0379367c/58556/high-performance-identity-apis.webp","srcSet":"/static/da26686e342d94b3007681cd0379367c/61e93/high-performance-identity-apis.webp 200w,\n/static/da26686e342d94b3007681cd0379367c/1f5c5/high-performance-identity-apis.webp 400w,\n/static/da26686e342d94b3007681cd0379367c/58556/high-performance-identity-apis.webp 800w,\n/static/da26686e342d94b3007681cd0379367c/99238/high-performance-identity-apis.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vijay Singh Shekhawat","github":"code-vj","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/guest-post/authenticating-flutter-apps/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>User authentication is the process of validating a user's identity to ensure that they are who they claim to be. Implementing user authentication in your application is critical to prevent unauthorized users from accessing sensitive information.</p>\n<p>This tutorial focuses on implementing user authentication and registration in Flutter applications using the LoginRadius API.</p>\n<h2 id=\"prerequisites\" style=\"position:relative;\"><a href=\"#prerequisites\" aria-label=\"prerequisites permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Prerequisites</h2>\n<p>If you wish to follow along with this tutorial, you must have the following set up:</p>\n<ul>\n<li><a href=\"https://accounts.loginradius.com/auth.aspx\">Sign up for a free LoginRadius developer account</a></li>\n<li>Any IDE that has <a href=\"https://docs.flutter.dev/get-started/install\">Flutter SDK</a> installed (i.e., <a href=\"https://developer.android.com/studio\">Android Studio</a>, <a href=\"https://code.visualstudio.com/\">VSCode</a>)</li>\n<li>A basic understanding of <a href=\"https://dart.dev/\">Dart</a> and <a href=\"https://flutter.dev/\">Flutter</a></li>\n</ul>\n<p>This tutorial is verified with Flutter v2.5.1 and Android Studio v3.5.</p>\n<h2 id=\"getting-started-with-loginradius\" style=\"position:relative;\"><a href=\"#getting-started-with-loginradius\" aria-label=\"getting started with loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Getting Started with LoginRadius</h2>\n<h3 id=\"what-is-loginradius\" style=\"position:relative;\"><a href=\"#what-is-loginradius\" aria-label=\"what is loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is LoginRadius?</h3>\n<p>LoginRadius is a cloud-based, SaaS Customer Identity and Access Management (CIAM) platform that provides developers and businesses simplified and robust features for managing customer identity, privacy, and access. LoginRadius offers high-level, secure, and well-documented APIs for integrating User Authentication and Single Sign-on (SSO) into your application.</p>\n<h3 id=\"why-use-loginradius\" style=\"position:relative;\"><a href=\"#why-use-loginradius\" aria-label=\"why use loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why use LoginRadius?</h3>\n<p>LoginRadius offers:</p>\n<ul>\n<li>A scalable infrastructure</li>\n<li>Built-in security measures to improve user account security and safe user data management</li>\n<li>Advanced login options such as Social SSO and Passwordless Login to improve the user experience</li>\n<li>SDKs and well-documented APIs for seamless integration into your application</li>\n</ul>\n<p>So, with everything out of the way, let's get started.</p>\n<h2 id=\"setting-up-loginradius-for-your-application\" style=\"position:relative;\"><a href=\"#setting-up-loginradius-for-your-application\" aria-label=\"setting up loginradius for your application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting Up LoginRadius for Your Application</h2>\n<p>After creating an account with LoginRadius, it sets up a free app for you. This is the app in which you would integrate the LoginRadius API with Flutter. Here my app name is “tayy”.</p>\n<p><img src=\"/0d7ac3f6bd1f6f3ad31570d5b79c1ebd/app_window.webp\" alt=\"LoginRadius App Screen\"></p>\n<p>Next, you need to obtain your LoginRadius API credentials. To do so, login to your Dashboard and navigate to the <code>Configuration</code> tab in the sidebar menu. You will find your API credentials under the <code>API Key and Secret</code> section. Copy and store your <strong>APP Name</strong>, <strong>API Key</strong>, and <strong>API Secret</strong> somewhere safe and easily accessible.</p>\n<p><img src=\"/8a552a2950ebab3006e383386c6a11ef/configuration_tab.webp\" alt=\"LoginRadius Configuration Tab\"></p>\n<h2 id=\"integrating-loginradius-api-with-your-flutter-application\" style=\"position:relative;\"><a href=\"#integrating-loginradius-api-with-your-flutter-application\" aria-label=\"integrating loginradius api with your flutter application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Integrating LoginRadius API with Your Flutter Application.</h2>\n<h3 id=\"step-1-create-a-new-flutter-project\" style=\"position:relative;\"><a href=\"#step-1-create-a-new-flutter-project\" aria-label=\"step 1 create a new flutter project permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1: Create a New Flutter project</h3>\n<p>Create a new Flutter project and navigate to the folder of the application by running the following commands in your terminal:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">flutter create loginradius_example</span>\n<span class=\"grvsc-line\">cd loginradius_example</span></code></pre>\n<h3 id=\"step-2-install-dependencies\" style=\"position:relative;\"><a href=\"#step-2-install-dependencies\" aria-label=\"step 2 install dependencies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2: Install Dependencies</h3>\n<p>Next, you need to install the <code>dio</code> package as a dependency in our project. The <code>dio</code> package is a powerful HTTP client used for making network requests.</p>\n<p>Run the following command to get the newest version of the <code>dio</code> package in your project.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">flutter pub add dio</span></code></pre>\n<p>Then, install the dependency by running <code>flutter pub get</code> in your terminal.</p>\n<h3 id=\"project-structure\" style=\"position:relative;\"><a href=\"#project-structure\" aria-label=\"project structure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Project Structure</h3>\n<p>The project is being structured in this order:</p>\n<p><img src=\"/cb6ed60c36b1e957eec023d28a260df7/folder-structure.webp\" alt=\"Folder Structure\"></p>\n<ul>\n<li>Core (contains a class that handles network requests)</li>\n<li>Screens (the UI of our app)</li>\n<li>Utils (helper components)</li>\n</ul>\n<h3 id=\"step-3-setting-up-the-api-client-class\" style=\"position:relative;\"><a href=\"#step-3-setting-up-the-api-client-class\" aria-label=\"step 3 setting up the api client class permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3: Setting up the API Client Class</h3>\n<p>Create a new dart file named <code>api_client.dart</code> and import the <code>dio</code> package into the file, as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">import &#39;package:dio/dio.dart&#39;;</span></code></pre>\n<p>Now let’s create a class named <code>ApiClient</code> and initialize the <code>Dio</code> object in it. The <code>ApiClient</code> class will contain several methods for making network requests based on your features, including User Registration, User Login, Get User Profile Data, and User Logout.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">import &#39;package:dio/dio.dart&#39;;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">   final Dio _dio = Dio();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; registerUser() async {</span>\n<span class=\"grvsc-line\">        //IMPLEMENT USER REGISTRATION</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; login() async {</span>\n<span class=\"grvsc-line\">        //IMPLEMENT USER LOGIN</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; getUserProfileData() async {</span>\n<span class=\"grvsc-line\">        //GET USER PROFILE DATA</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; logout() async {</span>\n<span class=\"grvsc-line\">        //IMPLEMENT USER LOGOUT</span>\n<span class=\"grvsc-line\">     }</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<h3 id=\"step-4-implement-user-registration\" style=\"position:relative;\"><a href=\"#step-4-implement-user-registration\" aria-label=\"step 4 implement user registration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Implement User Registration</h3>\n<p>Before implementing the user registration functionality, you must first <a href=\"https://www.loginradius.com/developers/\">obtain the user registration endpoint URL from the LoginRadius API Docs</a>.</p>\n<p>After retrieving the endpoint URL, you need to send a POST request to the endpoint using the <code>Dio</code> package by passing in:</p>\n<ul>\n<li>the <code>apiKey</code> you obtained earlier as a query parameter;</li>\n<li>the <code>userData</code> as the request body; and,</li>\n<li>the <code>SOTT</code> key as a header, as shown below.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\">       Future&lt;Response&gt; registerUser(Map&lt;String, dynamic&gt;? userData) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.post(</span>\n<span class=\"grvsc-line\">              &#39;https://api.loginradius.com/identity/v2/auth/register&#39;,  //ENDPONT URL</span>\n<span class=\"grvsc-line\">              data: userData, //REQUEST BODY</span>\n<span class=\"grvsc-line\">              queryParameters: {&#39;apikey&#39;: &#39;YOUR_API_KEY&#39;},  //QUERY PARAMETERS</span>\n<span class=\"grvsc-line\">              options: Options(headers: {&#39;X-LoginRadius-Sott&#39;: &#39;YOUR_SOTT_KEY&#39;, //HEADERS</span>\n<span class=\"grvsc-line\">          }));</span>\n<span class=\"grvsc-line\">          //returns the successful json object</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          //returns the error object if there is</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<h3 id=\"step-5-implement-user-login\" style=\"position:relative;\"><a href=\"#step-5-implement-user-login\" aria-label=\"step 5 implement user login permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 5: Implement User Login</h3>\n<p>The below code snippet shows how you’ll send a POST request to the LoginRadius login endpoint URL <code>https://api.loginradius.com/identity/v2/auth/login</code>, passing in your <code>apiKey</code> as a query parameter and the <code>email</code> and <code>password</code> of the user as the request body.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\">       Future&lt;Response&gt; login(String email, String password) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.post(</span>\n<span class=\"grvsc-line\">            &#39;https://api.loginradius.com/identity/v2/auth/login&#39;,</span>\n<span class=\"grvsc-line\">            data: {</span>\n<span class=\"grvsc-line\">              &#39;email&#39;: email,</span>\n<span class=\"grvsc-line\">              &#39;password&#39;: password</span>\n<span class=\"grvsc-line\">            },</span>\n<span class=\"grvsc-line\">            queryParameters: {&#39;apikey&#39;: &#39;YOUR_API_KEY&#39;},</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          //returns the successful user data json object</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          //returns the error object if any</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<h3 id=\"step-6-get-user-profile-data\" style=\"position:relative;\"><a href=\"#step-6-get-user-profile-data\" aria-label=\"step 6 get user profile data permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 6: Get User Profile Data</h3>\n<p>To retrieve the user profile details, send a <code>GET</code> request to the Read Profile Endpoint URL <code>https://api.loginradius.com/identity/v2/auth/account</code>, passing in your <code>apiKey</code> as a query parameter and the user's access token as the header.</p>\n<blockquote>\n<p>The user’s access token is gotten from the successful response object of the User Login endpoint.</p>\n</blockquote>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">       Future&lt;Response&gt; getUserProfileData(String accesstoken) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.get(</span>\n<span class=\"grvsc-line\">            &#39;https://api.loginradius.com/identity/v2/auth/account&#39;,</span>\n<span class=\"grvsc-line\">            queryParameters: {&#39;apikey&#39;: &#39;YOUR_API_KEY&#39;},</span>\n<span class=\"grvsc-line\">            options: Options(</span>\n<span class=\"grvsc-line\">              headers: {</span>\n<span class=\"grvsc-line\">                &#39;Authorization&#39;: &#39;Bearer ${YOUR_ACCESS_TOKEN}&#39;,</span>\n<span class=\"grvsc-line\">              },</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<h3 id=\"step-7-implement-user-logout\" style=\"position:relative;\"><a href=\"#step-7-implement-user-logout\" aria-label=\"step 7 implement user logout permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 7: Implement User Logout</h3>\n<p>Finally, to implement the user logout functionality, you would send a <code>GET</code> request to the Invalidate User Access Token endpoint URL <code>https://api.loginradius.com/identity/v2/auth/access_token/InValidate</code>. This API call invalidates the user's active access token, requiring them to re-authenticate if they want to access their data.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">      Future&lt;Response&gt; logout(String accessToken) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.get(</span>\n<span class=\"grvsc-line\">            &#39;https://api.loginradius.com/identity/v2/auth/access_token/InValidate&#39;,</span>\n<span class=\"grvsc-line\">            queryParameters: {&#39;apikey&#39;: ApiSecret.apiKey},</span>\n<span class=\"grvsc-line\">            options: Options(</span>\n<span class=\"grvsc-line\">              headers: {&#39;Authorization&#39;: &#39;Bearer $accessToken&#39;},</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<p>That concludes the <code>ApiClient</code> class. Next, you'll build the UI for your Flutter application, making use of the methods you just created in the <code>ApiClient</code> class.</p>\n<h3 id=\"building-the-ui\" style=\"position:relative;\"><a href=\"#building-the-ui\" aria-label=\"building the ui permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Building the UI</h3>\n<p>Your Flutter application will consist of four screens, which include:</p>\n<ul>\n<li>Registration Screen</li>\n<li>Login Screen</li>\n<li>Home Screen</li>\n</ul>\n<p>Let’s begin by building the Registration Screen.</p>\n<h3 id=\"registration-screen\" style=\"position:relative;\"><a href=\"#registration-screen\" aria-label=\"registration screen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Registration Screen</h3>\n<p>The <code>RegistrationScreen</code> has two <code>TextFormField</code> widgets that serve as our <code>email</code> and <code>password</code> fields, as well as an <code>ElevatedButton</code> to handle event submission, as shown in the code snippet below from the <code>register.dart</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"> //...</span>\n<span class=\"grvsc-line\">    @override</span>\n<span class=\"grvsc-line\">    Widget build(BuildContext context) {</span>\n<span class=\"grvsc-line\">      Scaffold(</span>\n<span class=\"grvsc-line\">          backgroundColor: Colors.blueGrey[200],</span>\n<span class=\"grvsc-line\">          body: Form(</span>\n<span class=\"grvsc-line\">            key: _formKey,</span>\n<span class=\"grvsc-line\">            child: SizedBox(</span>\n<span class=\"grvsc-line\">              width: size.width,</span>\n<span class=\"grvsc-line\">              height: size.height,</span>\n<span class=\"grvsc-line\">              child: Align(</span>\n<span class=\"grvsc-line\">                alignment: Alignment.center,</span>\n<span class=\"grvsc-line\">                child: Container(</span>\n<span class=\"grvsc-line\">                  width: size.width * 0.85,</span>\n<span class=\"grvsc-line\">                  padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 30),</span>\n<span class=\"grvsc-line\">                  decoration: BoxDecoration(</span>\n<span class=\"grvsc-line\">                    color: Colors.white,</span>\n<span class=\"grvsc-line\">                    borderRadius: BorderRadius.circular(20),</span>\n<span class=\"grvsc-line\">                  ),</span>\n<span class=\"grvsc-line\">                  child: SingleChildScrollView(</span>\n<span class=\"grvsc-line\">                    child: Column(</span>\n<span class=\"grvsc-line\">                      crossAxisAlignment: CrossAxisAlignment.start,</span>\n<span class=\"grvsc-line\">                      children: &lt;Widget&gt;[</span>\n<span class=\"grvsc-line\">                        const Center(</span>\n<span class=\"grvsc-line\">                          child: Text(</span>\n<span class=\"grvsc-line\">                            &quot;Register&quot;,</span>\n<span class=\"grvsc-line\">                            style: TextStyle(</span>\n<span class=\"grvsc-line\">                              fontSize: 30,</span>\n<span class=\"grvsc-line\">                              fontWeight: FontWeight.bold,</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                        SizedBox(height: size.height * 0.05),</span>\n<span class=\"grvsc-line\">                        TextFormField(</span>\n<span class=\"grvsc-line\">                          validator: (value) =&gt;</span>\n<span class=\"grvsc-line\">                              Validator.validateEmail(value ?? &quot;&quot;),</span>\n<span class=\"grvsc-line\">                          controller: emailController,</span>\n<span class=\"grvsc-line\">                          keyboardType: TextInputType.emailAddress,</span>\n<span class=\"grvsc-line\">                          decoration: InputDecoration(</span>\n<span class=\"grvsc-line\">                            hintText: &quot;Email&quot;,</span>\n<span class=\"grvsc-line\">                            isDense: true,</span>\n<span class=\"grvsc-line\">                            border: OutlineInputBorder(</span>\n<span class=\"grvsc-line\">                              borderRadius: BorderRadius.circular(10),</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                        SizedBox(height: size.height * 0.03),</span>\n<span class=\"grvsc-line\">                        TextFormField(</span>\n<span class=\"grvsc-line\">                          obscureText: _showPassword,</span>\n<span class=\"grvsc-line\">                          validator: (value) =&gt;</span>\n<span class=\"grvsc-line\">                              Validator.validatePassword(value ?? &quot;&quot;),</span>\n<span class=\"grvsc-line\">                          controller: passwordController,</span>\n<span class=\"grvsc-line\">                          keyboardType: TextInputType.visiblePassword,</span>\n<span class=\"grvsc-line\">                          decoration: InputDecoration(</span>\n<span class=\"grvsc-line\">                            hintText: &quot;Password&quot;,</span>\n<span class=\"grvsc-line\">                            isDense: true,</span>\n<span class=\"grvsc-line\">                            border: OutlineInputBorder(</span>\n<span class=\"grvsc-line\">                              borderRadius: BorderRadius.circular(10),</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                        SizedBox(height: size.height * 0.06),</span>\n<span class=\"grvsc-line\">                        Row(</span>\n<span class=\"grvsc-line\">                          mainAxisAlignment: MainAxisAlignment.center,</span>\n<span class=\"grvsc-line\">                          children: [</span>\n<span class=\"grvsc-line\">                            Expanded(</span>\n<span class=\"grvsc-line\">                              child: ElevatedButton(</span>\n<span class=\"grvsc-line\">                                onPressed: _handleRegister,</span>\n<span class=\"grvsc-line\">                                style: ElevatedButton.styleFrom(</span>\n<span class=\"grvsc-line\">                                    primary: Colors.indigo,</span>\n<span class=\"grvsc-line\">                                    shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">                                        borderRadius: BorderRadius.circular(10)),</span>\n<span class=\"grvsc-line\">                                    padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                                        horizontal: 40, vertical: 15)),</span>\n<span class=\"grvsc-line\">                                child: const Text(</span>\n<span class=\"grvsc-line\">                                  &quot;Register&quot;,</span>\n<span class=\"grvsc-line\">                                  style: TextStyle(</span>\n<span class=\"grvsc-line\">                                    fontSize: 20,</span>\n<span class=\"grvsc-line\">                                    fontWeight: FontWeight.bold,</span>\n<span class=\"grvsc-line\">                                  ),</span>\n<span class=\"grvsc-line\">                                ),</span>\n<span class=\"grvsc-line\">                              ),</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ],</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                      ],</span>\n<span class=\"grvsc-line\">                    ),</span>\n<span class=\"grvsc-line\">                  ),</span>\n<span class=\"grvsc-line\">                ),</span>\n<span class=\"grvsc-line\">              ),</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">          ),</span>\n<span class=\"grvsc-line\">        );</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">    //...</span></code></pre>\n<p>In the <code>onPressed</code> callback of the <code>ElevatedButton</code> widget, you'll handle the validation of your form data.</p>\n<p>If the form is validated, you pass your <code>userData</code> to the <code>registerUser</code> method from the <code>ApiClient</code> class for processing.</p>\n<p>If the response is an error, you show a snackbar with the error message. Otherwise, the user is redirected to the Login Screen.</p>\n<blockquote>\n<p>In the following example, you've provided only a few user attributes as <code>userData</code>. To view the complete list of user attributes, please look at the body parameters of the User Registration API here.</p>\n</blockquote>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Future&lt;void&gt; _handleRegister() async {</span>\n<span class=\"grvsc-line\">    if (_formKey.currentState!.validate()) {</span>\n<span class=\"grvsc-line\">    //show snackbar to indicate loading</span>\n<span class=\"grvsc-line\">     ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">        content: const Text(&#39;Processing Data&#39;),</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.green.shade300,</span>\n<span class=\"grvsc-line\">      ));</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">   //the user data to be sent</span>\n<span class=\"grvsc-line\">    Map&lt;String, dynamic&gt; userData = {</span>\n<span class=\"grvsc-line\">      &quot;Email&quot;: [</span>\n<span class=\"grvsc-line\">        {</span>\n<span class=\"grvsc-line\">          &quot;Type&quot;: &quot;Primary&quot;,</span>\n<span class=\"grvsc-line\">          &quot;Value&quot;: emailController.text,</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      ],</span>\n<span class=\"grvsc-line\">      &quot;Password&quot;: passwordController.text,</span>\n<span class=\"grvsc-line\">      &quot;About&quot;: &#39;I am a new user :smile:&#39;,</span>\n<span class=\"grvsc-line\">      &quot;FirstName&quot;: &quot;Test&quot;,</span>\n<span class=\"grvsc-line\">      &quot;LastName&quot;: &quot;Account&quot;,</span>\n<span class=\"grvsc-line\">      &quot;BirthDate&quot;: &quot;10-12-1985&quot;,</span>\n<span class=\"grvsc-line\">      &quot;Gender&quot;: &quot;M&quot;,</span>\n<span class=\"grvsc-line\">    };</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    //get response from ApiClient</span>\n<span class=\"grvsc-line\">    dynamic res = await _apiClient.registerUser(userData);</span>\n<span class=\"grvsc-line\">    ScaffoldMessenger.of(context).hideCurrentSnackBar();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    //checks if there is no error in the response body.</span>\n<span class=\"grvsc-line\">    //if error is not present, navigate the users to Login Screen.</span>\n<span class=\"grvsc-line\">    if (res[&#39;ErrorCode&#39;] == null) {</span>\n<span class=\"grvsc-line\">      Navigator.push(context,</span>\n<span class=\"grvsc-line\">          MaterialPageRoute(builder: (context) =&gt; const LoginScreen()));</span>\n<span class=\"grvsc-line\">    } else {</span>\n<span class=\"grvsc-line\">     //if error is present, display a snackbar showing the error messsage</span>\n<span class=\"grvsc-line\">      ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">        content: Text(&#39;Error: ${res[&#39;Message&#39;]}&#39;),</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.red.shade300,</span>\n<span class=\"grvsc-line\">      ));</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">  }</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<h3 id=\"login-screen\" style=\"position:relative;\"><a href=\"#login-screen\" aria-label=\"login screen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Login Screen</h3>\n<p>The <code>LoginScreen</code> UI code is similar to the <code>RegistrationScreen</code> in that it also has two <code>TextFormField</code> widgets that serve as our <code>email</code> and <code>password</code> fields, as well as an <code>ElevatedButton</code> to handle event submission. So, for the sake of brevity, I’ll be leaving out the <code>LoginScreen</code> UI code and focusing mainly on the code to be written in the <code>ElevatedButton</code> onPressed callback in the <code>login_screen.dart</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">//...</span>\n<span class=\"grvsc-line\">    //...</span>\n<span class=\"grvsc-line\">       Future&lt;void&gt; loginUsers() async {</span>\n<span class=\"grvsc-line\">        if (_formKey.currentState!.validate()) {</span>\n<span class=\"grvsc-line\">          //show snackbar to indicate loading</span>\n<span class=\"grvsc-line\">          ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">            content: const Text(&#39;Processing Data&#39;),</span>\n<span class=\"grvsc-line\">            backgroundColor: Colors.green.shade300,</span>\n<span class=\"grvsc-line\">          ));</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">          //get response from ApiClient</span>\n<span class=\"grvsc-line\">          dynamic res = await _apiClient.login(</span>\n<span class=\"grvsc-line\">            emailController.text,</span>\n<span class=\"grvsc-line\">            passwordController.text,</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          ScaffoldMessenger.of(context).hideCurrentSnackBar();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">          //if there is no error, get the user&#39;s accesstoken and pass it to HomeScreen</span>\n<span class=\"grvsc-line\">          if (res[&#39;ErrorCode&#39;] == null) {</span>\n<span class=\"grvsc-line\">            String accessToken = res[&#39;access_token&#39;];</span>\n<span class=\"grvsc-line\">            Navigator.push(</span>\n<span class=\"grvsc-line\">                context,</span>\n<span class=\"grvsc-line\">                MaterialPageRoute(</span>\n<span class=\"grvsc-line\">                    builder: (context) =&gt; HomeScreen(accesstoken: accessToken)));</span>\n<span class=\"grvsc-line\">          } else {</span>\n<span class=\"grvsc-line\">          //if an error occurs, show snackbar with error message</span>\n<span class=\"grvsc-line\">          ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">            content: Text(&#39;Error: ${res[&#39;Message&#39;]}&#39;),</span>\n<span class=\"grvsc-line\">            backgroundColor: Colors.red.shade300,</span>\n<span class=\"grvsc-line\">          ));</span>\n<span class=\"grvsc-line\">          }</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    //...</span></code></pre>\n<p>The code snippet above is a method that first validates the form before passing the <code>email</code> and <code>password</code> values to the <code>login</code> method from the <code>ApiClient</code> class for handling.</p>\n<p>If the response is successful, you obtain the user’s <code>access_token</code> from the response data and pass it over to the <code>HomeScreen</code>. Otherwise, you display a snackbar with the error message that occurred.</p>\n<p>Then, you pass the <code>loginUsers</code> method you created above to the <code>onPressed</code> property of the <code>ElevatedButton</code> widget in the <code>LoginScreen</code>, as shown below.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">    ElevatedButton(</span>\n<span class=\"grvsc-line\">        onPressed: loginUsers, //&lt;--</span>\n<span class=\"grvsc-line\">        style: ElevatedButton.styleFrom(</span>\n<span class=\"grvsc-line\">        primary: Colors.indigo,</span>\n<span class=\"grvsc-line\">        shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">               borderRadius: BorderRadius.circular(10)),</span>\n<span class=\"grvsc-line\">               padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                        horizontal: 40, vertical: 15)),</span>\n<span class=\"grvsc-line\">        child: const Text(&quot;Login&quot;,</span>\n<span class=\"grvsc-line\">            style: TextStyle(</span>\n<span class=\"grvsc-line\">                fontSize: 20,</span>\n<span class=\"grvsc-line\">                fontWeight: FontWeight.bold,</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">           ),</span>\n<span class=\"grvsc-line\">         ),</span>\n<span class=\"grvsc-line\">       ),</span></code></pre>\n<p>Next, you need to provide a screen that reveals the user's profile data when they successfully log in, and the <code>HomeScreen</code> is there to do so.</p>\n<h3 id=\"home-screen\" style=\"position:relative;\"><a href=\"#home-screen\" aria-label=\"home screen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Home Screen</h3>\n<p>The <code>HomeScreen</code> displays the user’s profile details using a <code>FutureBuilder</code> widget that accepts a future <code>getUserData</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">      Future&lt;Map&lt;String, dynamic&gt;&gt; getUserData() async {</span>\n<span class=\"grvsc-line\">        dynamic userRes;</span>\n<span class=\"grvsc-line\">        userRes = await _apiClient.getUserProfileData(widget.accesstoken);</span>\n<span class=\"grvsc-line\">        return userRes;</span>\n<span class=\"grvsc-line\">      }</span></code></pre>\n<p>The <code>getUserData</code> method above is used to retrieve details of a user by passing in the <code>access_token</code> obtained earlier from the <code>LoginScreen</code> to the <code>ApiClient</code> <code>getUserProfileData</code> method.</p>\n<p>To display the result of your <code>getUserData</code> method on our screen, use a <code>FutureBuilder</code> widget. The code snippet below shows how to use the <code>FutureBuilder</code> to get the results of the <code>getUserData</code> future in the <code>home.dart</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">    class HomeScreen extends StatefulWidget {</span>\n<span class=\"grvsc-line\">      final String accesstoken;</span>\n<span class=\"grvsc-line\">      const HomeScreen({Key? key, required this.accesstoken}) : super(key: key);</span>\n<span class=\"grvsc-line\">      @override</span>\n<span class=\"grvsc-line\">      State&lt;HomeScreen&gt; createState() =&gt; _HomeScreenState();</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">    class _HomeScreenState extends State&lt;HomeScreen&gt; {</span>\n<span class=\"grvsc-line\">      //instance of ApiClient class</span>\n<span class=\"grvsc-line\">      final ApiClient _apiClient = ApiClient();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">      //get user data from ApiClient</span>\n<span class=\"grvsc-line\">      Future&lt;Map&lt;String, dynamic&gt;&gt; getUserData() async {</span>\n<span class=\"grvsc-line\">        dynamic userRes;</span>\n<span class=\"grvsc-line\">        userRes = await _apiClient.getUserProfileData(widget.accesstoken);</span>\n<span class=\"grvsc-line\">        return userRes;</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">      @override</span>\n<span class=\"grvsc-line\">      Widget build(BuildContext context) {</span>\n<span class=\"grvsc-line\">        var size = MediaQuery.of(context).size;</span>\n<span class=\"grvsc-line\">        return Scaffold(</span>\n<span class=\"grvsc-line\">          backgroundColor: Colors.white,</span>\n<span class=\"grvsc-line\">          body: SizedBox(</span>\n<span class=\"grvsc-line\">              width: size.width,</span>\n<span class=\"grvsc-line\">              height: size.height,</span>\n<span class=\"grvsc-line\">              child: FutureBuilder&lt;Map&lt;String, dynamic&gt;&gt;(</span>\n<span class=\"grvsc-line\">                future: getUserData(), //&lt;---</span>\n<span class=\"grvsc-line\">                builder: (context, snapshot) {</span>\n<span class=\"grvsc-line\">                  if (snapshot.hasData) {</span>\n<span class=\"grvsc-line\">                    if (snapshot.connectionState == ConnectionState.waiting) {</span>\n<span class=\"grvsc-line\">                      return Container(</span>\n<span class=\"grvsc-line\">                        height: size.height,</span>\n<span class=\"grvsc-line\">                        width: size.width,</span>\n<span class=\"grvsc-line\">                        color: Colors.blueGrey,</span>\n<span class=\"grvsc-line\">                        child: const Center(</span>\n<span class=\"grvsc-line\">                          child: CircularProgressIndicator(),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                      );</span>\n<span class=\"grvsc-line\">                    }</span>\n<span class=\"grvsc-line\">                    //get results from snapshot</span>\n<span class=\"grvsc-line\">                    String fullName = snapshot.data![&#39;FullName&#39;];</span>\n<span class=\"grvsc-line\">                    String firstName = snapshot.data![&#39;FirstName&#39;];</span>\n<span class=\"grvsc-line\">                    String lastName = snapshot.data![&#39;LastName&#39;];</span>\n<span class=\"grvsc-line\">                    String birthDate = snapshot.data![&#39;BirthDate&#39;];</span>\n<span class=\"grvsc-line\">                    String email = snapshot.data![&#39;Email&#39;][0][&#39;Value&#39;];</span>\n<span class=\"grvsc-line\">                    String gender = snapshot.data![&#39;Gender&#39;];</span>\n<span class=\"grvsc-line\">                    return Container(</span>\n<span class=\"grvsc-line\">                      width: size.width,</span>\n<span class=\"grvsc-line\">                      height: size.height,</span>\n<span class=\"grvsc-line\">                      color: Colors.blueGrey.shade400,</span>\n<span class=\"grvsc-line\">                      child: SingleChildScrollView(</span>\n<span class=\"grvsc-line\">                        physics: const BouncingScrollPhysics(),</span>\n<span class=\"grvsc-line\">                     //...</span>\n<span class=\"grvsc-line\">                //...</span></code></pre>\n<p>Finally, let's add the logout feature.</p>\n<p>Add an <code>ElevatedButton</code> widget to the <code>HomeScreen</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">     TextButton(</span>\n<span class=\"grvsc-line\">        onPressed: (){},</span>\n<span class=\"grvsc-line\">        style: TextButton.styleFrom(</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.redAccent.shade700,</span>\n<span class=\"grvsc-line\">        shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">               borderRadius: BorderRadius.circular(5)),</span>\n<span class=\"grvsc-line\">               padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                    vertical: 15, horizontal: 25)),</span>\n<span class=\"grvsc-line\">        child: const Text(&#39;Logout&#39;,</span>\n<span class=\"grvsc-line\">          style: TextStyle(color: Colors.white),           ),</span>\n<span class=\"grvsc-line\">        ),</span>\n<span class=\"grvsc-line\">     ),</span></code></pre>\n<p>On pressing the button, you'll call the <code>logout</code> method on the <code>ApiClient</code> class and pass in the <code>access_token</code> value, and then you route the user to the <code>LoginScreen</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">     TextButton(</span>\n<span class=\"grvsc-line\">        onPressed: () async {</span>\n<span class=\"grvsc-line\">          await _apiClient.logout(widget.accesstoken);</span>\n<span class=\"grvsc-line\">          Navigator.pushReplacement(</span>\n<span class=\"grvsc-line\">            context, MaterialPageRoute(builder: (context) =&gt; const LoginScreen()));</span>\n<span class=\"grvsc-line\">        },</span>\n<span class=\"grvsc-line\">        style: TextButton.styleFrom(</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.redAccent.shade700,</span>\n<span class=\"grvsc-line\">        shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">               borderRadius: BorderRadius.circular(5)),</span>\n<span class=\"grvsc-line\">               padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                    vertical: 15, horizontal: 25)),</span>\n<span class=\"grvsc-line\">        child: const Text(&#39;Logout&#39;,</span>\n<span class=\"grvsc-line\">             style: TextStyle(color: Colors.white),</span>\n<span class=\"grvsc-line\">          ),</span>\n<span class=\"grvsc-line\">     ),</span></code></pre>\n<p><img src=\"/968d860d94a6f5f996e709e22dcec84a/demo-project.gif\" alt=\"Preview of demo project\"></p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>LoginRadius provides high-level, secure, and well-documented APIs to ease the implementation of authentication and user identity management. This tutorial has discussed LoginRadius's benefits and how to use the LoginRadius APIs to handle user authentication and registration in a Flutter application.</p>\n<p>The complete <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Flutter/Flutter_Auth_Guide\">source code of the demo application is available on GitHub</a>.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"February 17, 2022","updated_date":null,"title":"Flutter Authentication: Implementing User Signup and Login","tags":["Authentication","Flutter","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/97c4aaf6f0e898b457c0574ba1f8c979/58556/user-authentication-for-flutter-apps.webp","srcSet":"/static/97c4aaf6f0e898b457c0574ba1f8c979/61e93/user-authentication-for-flutter-apps.webp 200w,\n/static/97c4aaf6f0e898b457c0574ba1f8c979/1f5c5/user-authentication-for-flutter-apps.webp 400w,\n/static/97c4aaf6f0e898b457c0574ba1f8c979/58556/user-authentication-for-flutter-apps.webp 800w,\n/static/97c4aaf6f0e898b457c0574ba1f8c979/99238/user-authentication-for-flutter-apps.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Yusuf Ahmed","github":null,"avatar":null}}}},{"node":{"fields":{"slug":"/engineering/guest-post/securing-flask-api-with-jwt/"},"html":"<p>Authentication is an essential part of any web application. But unfortunately, it is not always easy to implement.</p>\n<h2 id=\"what-is-authentication\" style=\"position:relative;\"><a href=\"#what-is-authentication\" aria-label=\"what is authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Authentication?</h2>\n<p>Authentication is a process of verifying that an entity is who they claim to be. For example, a user might authenticate by providing a username and password. If the username and password are valid, the system will check if the user can access the resource. After the system checks the user's details against its database and if the details are valid, the user is thus authenticated and can access available resources.</p>\n<h2 id=\"authentication-factors\" style=\"position:relative;\"><a href=\"#authentication-factors\" aria-label=\"authentication factors permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Authentication Factors</h2>\n<p>The following factors are used to authenticate a user.</p>\n<h3 id=\"single-factor-authentication\" style=\"position:relative;\"><a href=\"#single-factor-authentication\" aria-label=\"single factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Single-factor Authentication</h3>\n<p>This authentication is used when a user provides a username/email/phone number and a password. This is the most common and weakest authentication factor. The user simply inputs the email and password, and the system checks if the data is valid; if valid, the user gets authenticated and can access the resource. What happens if another person who is not a legitimate user tries to access the resource? The system denies access to the resource.</p>\n<h3 id=\"multi-factor-authentication\" style=\"position:relative;\"><a href=\"#multi-factor-authentication\" aria-label=\"multi factor authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><a href=\"https://www.loginradius.com/multi-factor-authentication/\">Multi-factor Authentication</a></h3>\n<p>This authentication uses more than one factor to authenticate a user. For example, the user tries to log in with, say, email and password; if the data is correct, a code is sent to the user's phone number, and the user is asked to input the code. If the user enters the code, the user gets logged in; otherwise, the user is not authenticated. Some applications even go a step further by not using two factors but using three factors.</p>\n<h2 id=\"types-of-authentication\" style=\"position:relative;\"><a href=\"#types-of-authentication\" aria-label=\"types of authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Types of Authentication</h2>\n<p>There are three types of authentication, as follows:</p>\n<ol>\n<li><strong>Knowledge Authentication</strong>: The user is asked something that only they can provide or know -- e.g., password. This is the most common type and also the easiest.</li>\n<li><strong>Property Authentication</strong>: The user is asked for something they own or possess. For example, they can use a hardware authentication device like YubiKey or an authenticator app on their phone. The idea is that users will be asked to set an authentication factor that verifies the identity more securely. This isn’t always used alone; it’s used alongside another authentication type, say, <code>Knowledge authentication</code>.</li>\n<li><strong>Biological Authentication</strong>: The user is asked to verify their identity using something biologically unique to them -- e.g., a fingerprint or iris scan.</li>\n</ol>\n<p>In most applications, knowledge and property authentication are used as an extra layer of authentication.</p>\n<h2 id=\"authentication-vs-authorization\" style=\"position:relative;\"><a href=\"#authentication-vs-authorization\" aria-label=\"authentication vs authorization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Authentication vs. Authorization</h2>\n<p>The following are the differences between authentication and authorization:</p>\n<ol>\n<li>Authentication verifies identity (usually through credential validation)) while authorization grants or denies permissions to a user.</li>\n<li>Authentication is used to verify that users are who they say they are. Authorization is used to verify that a user has permission to do something.</li>\n</ol>\n<h2 id=\"starter-application\" style=\"position:relative;\"><a href=\"#starter-application\" aria-label=\"starter application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Starter Application</h2>\n<p>In this tutorial, you'll work on authentication in flask middleware for an existing API built with <a href=\"https://flask.palletsprojects.com/en/2.0.x/\">Flask</a> and <a href=\"https://pymongo.readthedocs.io/en/stable/\">PyMongo</a>. The API is a book library API using which users can create books and upload cover images for the books and relevant data. PyMongo is used to connect to the mongo database. You'll use the PyJWT library to generate and verify JWT tokens for auth in flask.  </p>\n<blockquote>\n<p>You can learn <a href=\"https://www.loginradius.com/blog/engineering/guest-post/jwt-authentication-best-practices-and-when-to-use/\">more about JSON Web Tokens (JWT) here</a>.</p>\n</blockquote>\n<p>To get started, clone the repository and set up the application by running the following commands:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">git clone https://github.com/LoginRadius/engineering-blog-samples.git </span><span class=\"mtk3\"># Clone the repository</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">cd</span><span class=\"mtk1\"> /Flask/loginRadius-flask-auth </span><span class=\"mtk3\"># change directory</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">python3 -m venv env </span><span class=\"mtk3\"># create virtual environment; if you&#39;re using Windows, `py -m venv env`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">source</span><span class=\"mtk1\"> env/bin/activate </span><span class=\"mtk3\"># activate virtual environment, if you&#39;re using windows, env/Scripts/activate</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">pip install -r requirements.txt </span><span class=\"mtk3\"># install dependencies</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\"># https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/</span></span></code></pre>\n<p>The application is now set up and ready to run. You can run the app using the command <code>flask run</code> in the project directory. You can test that all the endpoints are working by testing the app in an API testing tool, like Postman.</p>\n<h2 id=\"authentication-middleware\" style=\"position:relative;\"><a href=\"#authentication-middleware\" aria-label=\"authentication middleware permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Authentication Middleware</h2>\n<p>As you've noticed, anybody can access the API; you need to restrict access to the API. Create new book data if they have the correct data, then add, delete, and update book data, but you don't want that. To do this, you need to implement an authentication middleware.</p>\n<p>When we talk about authentication with flask, middlewares are created in Flask by creating a decorator; a function can have multiple middlewares, and the order matters a lot. </p>\n<p>To create your auth middleware, you need to install PyJWT -- the library you'll use to generate tokens. You’ll also use Pillow to alter image data before saving them to disk. Run the following command to install the packages:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">pip install pyjwt pillow</span></span></code></pre>\n<p>You need to add a secret key to your application; this is what you should pass to JWT.</p>\n<p>Add the following to your <code>app.py</code> file below the app declaration.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\"># app = Flask(__name__)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">SECRET_KEY = os.environ.get(</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;this is a secret&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">print</span><span class=\"mtk1\">(SECRET_KEY)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">app.config[</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">] = SECRET_KEY</span></span></code></pre>\n<p>Let's create a file called <code>auth_middleware.py</code> in the root of your application and place the following inside this file:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> functools </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> wraps</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> jwt</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> request, abort</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> current_app</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> models</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">token_required</span><span class=\"mtk1\">(</span><span class=\"mtk12\">f</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">@wraps</span><span class=\"mtk1\">(f)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">decorated</span><span class=\"mtk1\">(*</span><span class=\"mtk12\">args</span><span class=\"mtk1\">, **</span><span class=\"mtk12\">kwargs</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        token = </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Authorization&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> request.headers:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            token = request.headers[</span><span class=\"mtk8\">&quot;Authorization&quot;</span><span class=\"mtk1\">].split(</span><span class=\"mtk8\">&quot; &quot;</span><span class=\"mtk1\">)[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> token:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Authentication Token is missing!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">401</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data=jwt.decode(token, current_app.config[</span><span class=\"mtk8\">&quot;SECRET_KEY&quot;</span><span class=\"mtk1\">], </span><span class=\"mtk12\">algorithms</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;HS256&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            current_user=models.User().get_by_id(data[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> current_user </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">None</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid Authentication token!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">401</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> current_user[</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                abort(</span><span class=\"mtk7\">403</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> f(current_user, *args, **kwargs)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> decorated</span></span></code></pre>\n<p>The function above is simply a decorator function. Inside this function, you check if there is an <code>Authorization</code> field in the headers part of the request; if this is missing, you return an authorization error.</p>\n<p>Next, you check if it exists but is not valid; if it is not valid, you also return an authorization error.</p>\n<p>If everything goes fine, then the view function is called. As you can see, you return <code>f(current_user, *args, **kwargs)</code>, where <code>f</code> is the next decorator or function that's being called after this decorator -- in your case, the view function, which means that the first argument of any view function that uses this decorator must be <code>current_user</code>.</p>\n<h2 id=\"auth-routes\" style=\"position:relative;\"><a href=\"#auth-routes\" aria-label=\"auth routes permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Auth Routes</h2>\n<p>You currently have a route to creating a new user, but you don't have one to log in. From what you have above, you're checking if the token passed as the header is valid, but now the question is -- how do you get to know the token. Basically, the login route fetches the token and sends it to the client.</p>\n<p>Add the following function below the <code>add_user</code> function:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/login&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> data:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please provide user details&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\"># validate input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_email_and_password(data.get(</span><span class=\"mtk8\">&#39;email&#39;</span><span class=\"mtk1\">), data.get(</span><span class=\"mtk8\">&#39;password&#39;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Invalid data&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">data</span><span class=\"mtk1\">=</span><span class=\"mtk4\">None</span><span class=\"mtk1\">, </span><span class=\"mtk12\">error</span><span class=\"mtk1\">=is_validated), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = User().login(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk3\"># token should expire after 24 hrs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                user[</span><span class=\"mtk8\">&quot;token&quot;</span><span class=\"mtk1\">] = jwt.encode(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    {</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    app.config[</span><span class=\"mtk8\">&quot;SECRET_KEY&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">algorithm</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;HS256&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Successfully fetched auth token&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Error fetching auth token!, invalid email or password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">500</span></span></code></pre>\n<h2 id=\"protecting-api-routes-in-flask\" style=\"position:relative;\"><a href=\"#protecting-api-routes-in-flask\" aria-label=\"protecting api routes in flask permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Protecting API Routes in Flask</h2>\n<p>So far, you've been able to create your auth middleware, but you need to use this middleware to protect routes. All you need to do is to pass this middleware immediately after the <code>app.route</code> middleware, then make <code>current_user</code> the first argument of the view function, as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;/&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify(current_user)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;/&lt;pdt_id&gt;&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">product</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">pdt_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify(Product.find({</span><span class=\"mtk8\">&#39;user_id&#39;</span><span class=\"mtk1\">: pdt_id}))</span></span></code></pre>\n<p>Add this middleware (<code>@token_required</code>) to every function you only want authenticated users to access. In the end, your whole <code>app.py</code> file should look as follows.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> jwt, os</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> dotenv </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> load_dotenv</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Flask, request, jsonify</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> save_image </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> save_pic</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> validate </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> validate_book, validate_email_and_password, validate_user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">load_dotenv()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">app = Flask(</span><span class=\"mtk12\">__name__</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">SECRET_KEY = os.environ.get(</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;this is a secret&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">print</span><span class=\"mtk1\">(SECRET_KEY)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">app.config[</span><span class=\"mtk8\">&#39;SECRET_KEY&#39;</span><span class=\"mtk1\">] = SECRET_KEY</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> models </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Books, User</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> auth_middleware </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> token_required</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">hello</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Hello World!&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">add_user</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please provide user details&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_user(**user)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Invalid data&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">data</span><span class=\"mtk1\">=</span><span class=\"mtk4\">None</span><span class=\"mtk1\">, </span><span class=\"mtk12\">error</span><span class=\"mtk1\">=is_validated), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = User().create(**user)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;User already exists&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Conflict&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">409</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Successfully created new user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/login&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> data:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please provide user details&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\"># validate input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_email_and_password(data.get(</span><span class=\"mtk8\">&#39;email&#39;</span><span class=\"mtk1\">), data.get(</span><span class=\"mtk8\">&#39;password&#39;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Invalid data&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">data</span><span class=\"mtk1\">=</span><span class=\"mtk4\">None</span><span class=\"mtk1\">, </span><span class=\"mtk12\">error</span><span class=\"mtk1\">=is_validated), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = User().login(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk3\"># token should expire after 24 hrs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                user[</span><span class=\"mtk8\">&quot;token&quot;</span><span class=\"mtk1\">] = jwt.encode(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    {</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    app.config[</span><span class=\"mtk8\">&quot;SECRET_KEY&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">algorithm</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;HS256&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Successfully fetched auth token&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Error fetching auth token!, invalid email or password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Unauthorized&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;GET&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_current_user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully retrieved user profile&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: current_user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;PUT&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update_user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = request.json</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user.get(</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            user = User().update(current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">], user[</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully updated account&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }), </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid data, you can only update your account name!&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad Request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to update account&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/users/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;DELETE&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">disable_user</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        User().disable_account(current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully disabled acount&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">204</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to disable account&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">add_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = </span><span class=\"mtk10\">dict</span><span class=\"mtk1\">(request.form)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid data, you need to give the book title, cover image, author id,&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Bad Request&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> request.files[</span><span class=\"mtk8\">&quot;cover_image&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;cover image is required&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">] = request.host_url+</span><span class=\"mtk8\">&quot;static/books/&quot;</span><span class=\"mtk1\">+save_pic(request.files[</span><span class=\"mtk8\">&quot;cover_image&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">] = current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        is_validated = validate_book(**book)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> is_validated </span><span class=\"mtk4\">is</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">True</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Invalid data&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: is_validated</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().create(**book)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;The book has been created by user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Conflict&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully created a new book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to create a new book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;GET&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_books</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = Books().get_by_user_id(current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully retrieved all books&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: books</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to retrieve all books&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&lt;book_id&gt;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;GET&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Book not found&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Not Found&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully retrieved a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Something went wrong&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">500</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&lt;book_id&gt;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;PUT&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> book[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">] != current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Book not found for user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Not found&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = request.form</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> book.get(</span><span class=\"mtk8\">&#39;cover_image&#39;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            book[</span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">] = request.host_url+</span><span class=\"mtk8\">&quot;static/books/&quot;</span><span class=\"mtk1\">+save_pic(request.files[</span><span class=\"mtk8\">&quot;cover_image&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().update(book_id, **book)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully updated a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">201</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to update a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.route</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/books/&lt;book_id&gt;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">methods</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&quot;DELETE&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@token_required</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete_book</span><span class=\"mtk1\">(</span><span class=\"mtk12\">current_user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = Books().get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> book[</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">] != current_user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">]:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Book not found for user&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Not found&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }, </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        Books().delete(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;successfully deleted a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">204</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">except</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Exception</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> e:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;failed to delete a book&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }), </span><span class=\"mtk7\">400</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.errorhandler</span><span class=\"mtk1\">(</span><span class=\"mtk7\">403</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">forbidden</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Forbidden&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }), </span><span class=\"mtk7\">403</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">@app.errorhandler</span><span class=\"mtk1\">(</span><span class=\"mtk7\">404</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">forbidden</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> jsonify({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Endpoint Not Found&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;error&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(e),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;data&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }), </span><span class=\"mtk7\">404</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">__name__</span><span class=\"mtk1\"> == </span><span class=\"mtk8\">&quot;__main__&quot;</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    app.run(</span><span class=\"mtk12\">debug</span><span class=\"mtk1\">=</span><span class=\"mtk4\">True</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>Before running the application, let's look at the <code>save_pic</code> function inside the <code>save_image.py</code> file. This is the function responsible for saving uploaded pictures.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> PIL </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Image</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> secrets, os</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> flask </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> current_app </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> app</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">save_pic</span><span class=\"mtk1\">(</span><span class=\"mtk12\">picture</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    file_name = secrets.token_hex(</span><span class=\"mtk7\">8</span><span class=\"mtk1\">) +os.path.splitext(picture.filename)[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> os.path.isdir(os.path.join(app.root_path, </span><span class=\"mtk8\">&#39;static&#39;</span><span class=\"mtk1\">)):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> os.path.isdir(os.path.join(app.root_path, </span><span class=\"mtk8\">&#39;static/images&#39;</span><span class=\"mtk1\">)):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> os.path.isdir(os.path.join(app.root_path, </span><span class=\"mtk8\">&#39;static/images/books&#39;</span><span class=\"mtk1\">)):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        os.mkdir(os.path.join(app.root_path,</span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    file_path = os.path.join(app.root_path, </span><span class=\"mtk8\">&quot;static/images/books&quot;</span><span class=\"mtk1\">, file_name)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    picture = Image.open(picture)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    picture.thumbnail((</span><span class=\"mtk7\">150</span><span class=\"mtk1\">, </span><span class=\"mtk7\">150</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    picture.save(file_path)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> file_name</span></span></code></pre>\n<p>You should also add the following functions as helper methods of the <code>User</code> model class.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">disable_account</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user = db.users.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        {</span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: {</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">False</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">encrypt_password</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> generate_password_hash(password)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&quot;&quot;Login a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_email(email)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> check_password_hash(user[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">], password):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    user.pop(</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span></code></pre>\n<p>Your <code>models.py</code> file should look as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk8\">&quot;&quot;&quot;Application Models&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> bson, os</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> dotenv </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> load_dotenv</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> pymongo </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> MongoClient</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> werkzeug.security </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> generate_password_hash, check_password_hash</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">load_dotenv()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">DATABASE_URL=os.environ.get(</span><span class=\"mtk8\">&#39;DATABASE_URL&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;mongodb://localhost:27017/myDatabase&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">print</span><span class=\"mtk1\">(DATABASE_URL)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">client = MongoClient(DATABASE_URL)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">db = client.myDatabase</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Books</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&quot;&quot;Books Model&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">__init__</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">create</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">description</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">image_url</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Create a new book&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_user_id_and_title(user_id, title)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        new_book = db.books.insert_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk1\">: title,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;description&quot;</span><span class=\"mtk1\">: description,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">: image_url,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">: category,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(new_book.inserted_id)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_all</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**book, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a book by id&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.find_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(book_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_user_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books created by a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**book, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_category</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books by category&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find({</span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">: category})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [book </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_user_id_and_category</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all books by category for a particular user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        books = db.books.find({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id, </span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">: category})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**book, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> book </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> books]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_user_id_and_title</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">title</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a book given its title and author&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.find_one({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: user_id, </span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk1\">: title})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> book:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(book[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">description</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">image_url</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">category</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Update a book&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data={}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> title: data[</span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk1\">]=title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> description: data[</span><span class=\"mtk8\">&quot;description&quot;</span><span class=\"mtk1\">]=description</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> image_url: data[</span><span class=\"mtk8\">&quot;image_url&quot;</span><span class=\"mtk1\">]=image_url</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> category: data[</span><span class=\"mtk8\">&quot;category&quot;</span><span class=\"mtk1\">]=category</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(book_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: data</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(book_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">book_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Delete a book&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.delete_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(book_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete_by_user_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Delete all books created by a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        book = db.books.delete_many({</span><span class=\"mtk8\">&quot;user_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">User</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&quot;&quot;User Model&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">__init__</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">create</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Create a new user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_email(email)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        new_user = db.users.insert_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">: name,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">: email,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.encrypt_password(password),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(new_user.inserted_id)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_all</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get all users&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        users = db.users.find({</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [{**user, </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])} </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> user </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> users]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_id</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a user by id&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.find_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id), </span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user.pop(</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">get_by_email</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Get a user by email&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.find_one({</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">: email, </span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">True</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk10\">str</span><span class=\"mtk1\">(user[</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">update</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Update a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        data = {}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> name:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            data[</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk1\">] = name</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: data</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Delete a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        Books().delete_by_user_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.delete_one({</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">disable_account</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user_id</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Disable a user account&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = db.users.update_one(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: bson.ObjectId(user_id)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            {</span><span class=\"mtk8\">&quot;$set&quot;</span><span class=\"mtk1\">: {</span><span class=\"mtk8\">&quot;active&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">False</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_id(user_id)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">encrypt_password</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Encrypt password&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> generate_password_hash(password)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">, </span><span class=\"mtk12\">email</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;&quot;&quot;Login a user&quot;&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.get_by_email(email)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> user </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> check_password_hash(user[</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">], password):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        user.pop(</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> user</span></span></code></pre>\n<p>Here's an example of the user request:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">     &quot;name&quot; : &quot;abc xyz&quot;,</span>\n<span class=\"grvsc-line\">     &quot;email&quot; : &quot;xyz@gmail.com&quot;,</span>\n<span class=\"grvsc-line\">     &quot;password&quot; : &quot;Abc@123&quot;</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>Here, the name should have two words, and the password should have at least an uppercase later, a lower case letter, a digit, and a special character.</p>\n<p>And an example of the book request:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">    &quot;title&quot;:&quot;name of book&quot;,</span>\n<span class=\"grvsc-line\">    &quot;cover_image&quot;: &quot;path to image file locally&quot;,</span>\n<span class=\"grvsc-line\">    &quot;category&quot;: &quot;[&#39;romance&#39;, &#39;peotry&#39;, &#39;politics&#39;, &#39;picture book&#39;, &#39;science&#39;, &#39;fantasy&#39;, &#39;horror&#39;, &#39;thriller&#39;],</span>\n<span class=\"grvsc-line\">    &quot;description&quot;:&quot;description&quot;,</span>\n<span class=\"grvsc-line\">    &quot;user_id&quot;:&quot;user_id&quot;</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>While passing a book request, pass it via the <code>form-data</code> tab in Postman.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>This article has explained flask JWT authentication .</p>\n<p>In some cases, handling flask authentication yourself may not be good enough or efficient -- to overcome this, you can simply use third-party authentication providers like LoginRadius. You can check out this tutorial to learn how to add LoginRadius to your Flask application.</p>\n<p>You can find the complete code for this article on <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Flask/loginRadius-flask-auth\">Github</a>. You can reach out to me on <a href=\"https://twitter.com/bkoiki950\">Twitter</a> if you've any questions.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"December 09, 2021","updated_date":null,"title":"Using JWT Flask JWT Authentication- A Quick Guide","tags":["Flask","JWT","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/1cfc51c7d9ade423f3b1992809ba5b1b/58556/coverImage.webp","srcSet":"/static/1cfc51c7d9ade423f3b1992809ba5b1b/61e93/coverImage.webp 200w,\n/static/1cfc51c7d9ade423f3b1992809ba5b1b/1f5c5/coverImage.webp 400w,\n/static/1cfc51c7d9ade423f3b1992809ba5b1b/58556/coverImage.webp 800w,\n/static/1cfc51c7d9ade423f3b1992809ba5b1b/99238/coverImage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Babatunde Koiki","github":"Babatunde13","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/github-api/"},"html":"<h1 id=\"introduction-to-github-apis\" style=\"position:relative;\"><a href=\"#introduction-to-github-apis\" aria-label=\"introduction to github apis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction to Github APIs</h1>\n<h2 id=\"what-are-apis\" style=\"position:relative;\"><a href=\"#what-are-apis\" aria-label=\"what are apis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What are APIs</h2>\n<p>API stands for Application Program Interfaces, which developers use to access web tools or information on the cloud. It allows different cross-platform applications to talk to each other.\nOne of the common examples of it is <a href=\"https://cloud.google.com/speech-to-text\">Google Speech to Text API</a> used when you talk to Google Assistant.</p>\n<h2 id=\"what-is-github-apis\" style=\"position:relative;\"><a href=\"#what-is-github-apis\" aria-label=\"what is github apis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is <a href=\"https://developer.github.com/v3/\">Github APIs</a></h2>\n<p>Github APIs( or Github ReST APIs) are the APIs that you can use to interact with GitHub. They allow you to create and manage repositories, branches, issues, pull requests, and many more.\nFor fetching publicly available information (like public repositories, user profiles, etc.), you can call the API. For other actions, you need to provide an authenticated token.</p>\n<h2 id=\"basic-github-apis-examples\" style=\"position:relative;\"><a href=\"#basic-github-apis-examples\" aria-label=\"basic github apis examples permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Basic Github APIs Examples</h2>\n<p>The base URL for GitHub APIs is:- <a href=\"https://api.github.com/\">GithubAPI</a></p>\n<h3 id=\"accessing-public-information\" style=\"position:relative;\"><a href=\"#accessing-public-information\" aria-label=\"accessing public information permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Accessing Public Information</h3>\n<h4 id=\"fetching-user-information-with-its-username\" style=\"position:relative;\"><a href=\"#fetching-user-information-with-its-username\" aria-label=\"fetching user information with its username permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Fetching user information with its username</h4>\n<p>Request type: GET\nAPI endpoint: /users/{username}</p>\n<p>Example :- <code>curl https://api.github.com/users/devkapilbansal</code></p>\n<p><img src=\"/fcabf9d423b1a71e7e92aa365512c4e1/user_details.webp\" alt=\"user_details\"></p>\n<p>As you can see, API returns us a JSON response with info about the user, like its image<em>url, name, mail</em>address.</p>\n<h4 id=\"fetching-users-followers-list\" style=\"position:relative;\"><a href=\"#fetching-users-followers-list\" aria-label=\"fetching users followers list permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Fetching user's followers' list</h4>\n<p>Request type: GET\nAPI endpoint: /users/{username}/followers</p>\n<p>Example :- <code>curl https://api.github.com/devkapilbansal/followers</code></p>\n<p><img src=\"/1cae6a5b119732ee713738f1b2d9b51d/followers.webp\" alt=\"followers\"></p>\n<p>This URL returns info about all the users that follow a particular user.</p>\n<h4 id=\"check-if-a-user-follows-another\" style=\"position:relative;\"><a href=\"#check-if-a-user-follows-another\" aria-label=\"check if a user follows another permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Check if a user follows another</h4>\n<p>Request type: GET\nAPI endpoint: /user/{username}/following/{target_username}</p>\n<p>This endpoint doesn't return any content. It just returns a status code.</p>\n<p>A status code of 204 means the <code>target_user</code> is followed by the user, whereas a status code of 404 means the user does not follow a <code>target_user</code>.</p>\n<p>Example :- <code>curl https://api.github.com/devkapilbansal/following/KapilBansal</code></p>\n<p>When a user follows another user\n<img src=\"/57f8001411f9b8f5e38aad54e2d88e60/user_follows.webp\" alt=\"follow\"></p>\n<p>When a user doesn't follow another user\n<img src=\"/46b872a0a908417b69453e83a049ad01/user_not_follows.webp\" alt=\"not_follow\"></p>\n<h3 id=\"performing-tasks-as-an-authenticated-user\" style=\"position:relative;\"><a href=\"#performing-tasks-as-an-authenticated-user\" aria-label=\"performing tasks as an authenticated user permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Performing tasks as an authenticated user</h3>\n<p>If you provide an authenticated token, you don't need to provide a username in the endpoints mentioned above.</p>\n<p>By providing the token, you can create repositories/gists, comment on pull requests/issues, and all other tasks that you can perform from the Web Interface.</p>\n<h4 id=\"generating-token\" style=\"position:relative;\"><a href=\"#generating-token\" aria-label=\"generating token permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Generating Token</h4>\n<p>You can get a token by going to <a href=\"https://github.com/settings/tokens\">Personal access tokens</a> and clicking on <em>Generate new token</em>. You will be asked for the permissions/scopes of that token. Choose them <strong>wisely</strong> while creating one as some of these might be destructive.</p>\n<p>After selecting scopes, click on generate token and save the token somewhere as you will not see that token again.</p>\n<p><strong>Note</strong>:- Store your token in a secured environment while using it.</p>\n<h4 id=\"creating-a-repository\" style=\"position:relative;\"><a href=\"#creating-a-repository\" aria-label=\"creating a repository permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a Repository</h4>\n<p>Request type: POST\nAPI endpoint: /user/{repos}\nRequired data: name</p>\n<p>Example :- <code>curl -H \"Authorization: token ${token}\" -d '{\"name\":\"Github API Testing\"}' https://api.github.com/user/repos</code></p>\n<p><img src=\"/477483cdbc31361f442752fe4d10b405/create_repo.webp\" alt=\"create repo\"></p>\n<h4 id=\"list-issues-assigned-to-you\" style=\"position:relative;\"><a href=\"#list-issues-assigned-to-you\" aria-label=\"list issues assigned to you permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>List issues assigned to you</h4>\n<p>Request type: GET\nAPI endpoint: /issues</p>\n<p>Example :- <code>curl -H \"Authorization: token ${token}\" https://api.github.com/issues</code></p>\n<p><img src=\"/e8efdf1818159d6bb8dcaf3d93e9ae4e/list_issues.webp\" alt=\"list issues\"></p>\n<h4 id=\"creating-an-issue\" style=\"position:relative;\"><a href=\"#creating-an-issue\" aria-label=\"creating an issue permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating an issue</h4>\n<p>Request type: POST\nAPI endpoint: /repos/{owner}/{repo_name}/issues\nRequired data: title</p>\n<p>Example :- <code>curl -H \"Authorization: token ${token}\" -d '{\"title\":\"Issue_For_Test\"}' https://api.github.com/repos/devkapilbansal/Github-API-Testing/issues</code></p>\n<p><img src=\"/6af01c54b3e9188ccde7155223633e89/create_issue.webp\" alt=\"create_issue\"></p>\n<h4 id=\"commenting-on-issue\" style=\"position:relative;\"><a href=\"#commenting-on-issue\" aria-label=\"commenting on issue permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Commenting on issue</h4>\n<p>Request type: POST\nAPI endpoint: /repos/{owner}/{repo<em>name}/issues/{issue</em>no}/comments\nRequired data: body</p>\n<p>Example :- <code>curl -H \"Authorization: token ${token}\" -d '{\"body\":\"Test comment\"}' https://api.github.com/repos/devkapilbansal/Github-API-Testing/issues/1/comments</code></p>\n<p><img src=\"/4df61697608dded30f461414e40fe21d/comment_on_issue.webp\" alt=\"comment\"></p>\n<p><strong>Note</strong> - The same endpoint is used for commenting on pull requests too. Just change the issue number with the pull request number.</p>\n<h4 id=\"openingclosing-an-issue\" style=\"position:relative;\"><a href=\"#openingclosing-an-issue\" aria-label=\"openingclosing an issue permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Opening/Closing an issue</h4>\n<p>Request type: PUT\nAPI endpoint: /repos/{owner}/{repo<em>name}/issues/{issue</em>no}</p>\n<p>Example :- <code>curl -H \"Authorization: token ${token}\" -d '{\"state\":\"close\"}' https://api.github.com/repos/devkapilbansal/Github-API-Testing/issues/1</code></p>\n<p><strong>Note</strong> - The same endpoint is valid for updating pull requests too.</p>\n<h4 id=\"results\" style=\"position:relative;\"><a href=\"#results\" aria-label=\"results permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Results</h4>\n<p>The above results can be verified on the GitHub website too.\n<img src=\"/5a6d6e81b8243aeb1415ed6869a974c8/output.webp\" alt=\"results\"></p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>There are a lot more endpoints that you can explore at <a href=\"https://developer.github.com/v3\">Github</a>. Also, you can only do the work you are authorized to with that token.\nAlthough there are plenty of data fields that can be sent with these endpoints, only required ones are shown above.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"November 02, 2020","updated_date":null,"title":"Introduction to Github APIs","tags":["Github","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/9b0ec78bfd1a3c9406386c61f5dcb8c4/58556/GitHub_coverImage.webp","srcSet":"/static/9b0ec78bfd1a3c9406386c61f5dcb8c4/61e93/GitHub_coverImage.webp 200w,\n/static/9b0ec78bfd1a3c9406386c61f5dcb8c4/1f5c5/GitHub_coverImage.webp 400w,\n/static/9b0ec78bfd1a3c9406386c61f5dcb8c4/58556/GitHub_coverImage.webp 800w,\n/static/9b0ec78bfd1a3c9406386c61f5dcb8c4/99238/GitHub_coverImage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kapil Bansal","github":"devkapilbansal","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/what-is-graphql/"},"html":"<p>GraphQL's popularity has skyrocketed since its release in 2015. It is the modern way of developing and querying APIs. GraphQL is an application programming interface (API) query language and server-side runtime that prioritises giving customers precisely the data they request.</p>\n<p>GraphQL is designed to make fast, scalable, and <a href=\"/what-is-an-api/\">developer-friendly APIs</a>. GraphQL allows developers to build requests that pull data from multiple data sources in a single API call as an alternative to REST.</p>\n<h2 id=\"foundation-of-graphql\" style=\"position:relative;\"><a href=\"#foundation-of-graphql\" aria-label=\"foundation of graphql permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Foundation of GraphQL</h2>\n<p>It was developed internally by <a href=\"https://techcrunch.com/2018/11/06/facebooks-graphql-gets-its-own-open-source-foundation/\">Facebook in 2012</a> before being publicly released in 2015. \"On 7 November 2018, the GraphQL project was moved from Facebook to the newly-established GraphQL Foundation, hosted by the non-profit Linux Foundation.\"</p>\n<h2 id=\"what-is-graphql\" style=\"position:relative;\"><a href=\"#what-is-graphql\" aria-label=\"what is graphql permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is GraphQL?</h2>\n<p>GraphQL is an application-level query language that helps data fetching and serving between client and server runtime by providing a standard protocol for queries. Its strength lies in the fact that it offers a modern, simpler, and efficient way to query and develop APIs. The real deal is its <strong>flexible data fetching</strong> -- the application only loads relevant data from the server. Also, GraphQL is hierarchical in nature; it structures relationships in a simple hierarchical manner to avoid complex queries while fetching data.</p>\n<h2 id=\"why-to-use-graphql\" style=\"position:relative;\"><a href=\"#why-to-use-graphql\" aria-label=\"why to use graphql permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why to use GraphQL?</h2>\n<p>GraphQL <strong>offers much power and flexibility</strong> over Traditional APIs. One of the few things GraphQL was designed, was to solve Data Fetching/Loading problems.</p>\n<p>Data fetching is one of the most critical factors responsible for the performance of the application. Most of the time, the data provided by the API isn't required to run the application. This problem is termed as <strong>\"Over fetching\"</strong>, which can be a more significant issue in mobile devices. Since devices with slower network connection are bound to take more load time, it creates a <strong>negative impact on end-users.</strong></p>\n<p>In the current scenario, traditional <a href=\"/best-practice-guide-for-rest-api-security/\">REST APIs</a> offer no clean way to solve this problem; GraphQL comes to the rescue. It allows <strong>clients to define the structure of the data</strong> required, and the same structure of the data is returned from the server. Therefore preventing fetching loads and loads of data, ultimately increasing performance.</p>\n<p>API endpoints generally fetch specific data, hence to load a certain data-rich application, there have to be <strong>multiple requests to the server.</strong> But, applications should fetch relevant data in one round trip to avoid <strong>degrading performance.</strong> The flexibility and richness of the GraphQL, allows us to define all the data to fetch in a single request, avoiding multiple Round trips</p>\n<p><img src=\"/694f76479da4ca6d382a0378c1c401c9/wrapper.webp\" alt=\"Wrapping a REST API in GraphQL\">\n<em>Wrapping REST API in graphQL - Source - Joey Ng'ethe | TwigaTech</em></p>\n<h2 id=\"fundamentals-of-graphql\" style=\"position:relative;\"><a href=\"#fundamentals-of-graphql\" aria-label=\"fundamentals of graphql permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Fundamentals of GraphQL</h2>\n<table>\n<thead>\n<tr>\n<th>Server -></th>\n<th>GraphQL Server -></th>\n<th>Graphql Client -></th>\n<th>Client</th>\n</tr>\n</thead>\n<tbody>\n</tbody>\n</table>\n<hr>\n<p><strong>Schema</strong> - GraphQL follows a type system to define the schema of an API. The syntax for writing schemas is called Schema Definition Language (SDL).</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"># </span><span class=\"mtk12\">A</span><span class=\"mtk1\"> </span><span class=\"mtk12\">simple</span><span class=\"mtk1\"> </span><span class=\"mtk12\">example</span><span class=\"mtk1\"> </span><span class=\"mtk12\">to</span><span class=\"mtk1\"> </span><span class=\"mtk12\">define</span><span class=\"mtk1\"> </span><span class=\"mtk12\">schema</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Person</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  name: String!</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  age: Int!</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p><strong>Query</strong> - The data or information that a client needs from a server can be fetched in a request using queries.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"># This query fetches all specifically names of all users</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk14\">users</span><span class=\"mtk1\"> </span><span class=\"mtk14\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk14\">name</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"># This query fetches all names of all friends of user </span><span class=\"mtk8\">&quot;Anup&quot;</span><span class=\"mtk1\">.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk14\">user(name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Anup&quot;</span><span class=\"mtk14\">)</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk14\">name</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk14\">friend</span><span class=\"mtk1\"> </span><span class=\"mtk14\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk14\">name</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p><strong>Mutation</strong> - Mutations are the way to modify data to the server; these include creating/updating/deleting data. They have similar syntax as queries, with special keywords ahead of them.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"># This mutation adds a user with name </span><span class=\"mtk8\">&quot;Anup&quot;</span><span class=\"mtk1\"> and age </span><span class=\"mtk7\">20</span><span class=\"mtk1\">.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">mutation {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk14\">addUser(</span><span class=\"mtk1\"> </span><span class=\"mtk14\">name</span><span class=\"mtk1\"> : </span><span class=\"mtk8\">&quot;Anup&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk14\">age</span><span class=\"mtk1\">: </span><span class=\"mtk7\">20</span><span class=\"mtk14\">)</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk14\">name</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk14\">age</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Despite its powers, you might not need graphQL in your applications -</p>\n<ul>\n<li>Since it adds unnecessary overhead and complex architecture for simple applications.</li>\n<li>It makes web caching challenging to implement.</li>\n</ul>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>GraphQL is a step forward in the world of applications by providing a significant boost in performance. Another plus point of GraphQL is that it is not meant to replace any existing solution but enhance and co-exist with REST APIs. Simply put, the future of GraphQL looks bright.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk14 { color: #F44747; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"October 01, 2020","updated_date":null,"title":"What is GraphQL? - A Basic Guide","tags":["Engineering","API","GraphQL","Performance"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/4674ea0950b63a1ff2d08638af559bc0/58556/graph.webp","srcSet":"/static/4674ea0950b63a1ff2d08638af559bc0/61e93/graph.webp 200w,\n/static/4674ea0950b63a1ff2d08638af559bc0/1f5c5/graph.webp 400w,\n/static/4674ea0950b63a1ff2d08638af559bc0/58556/graph.webp 800w,\n/static/4674ea0950b63a1ff2d08638af559bc0/210c1/graph.webp 900w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Anup Aglawe","github":"anup-a","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/create-rest-api-in-deno/"},"html":"<p>Deno, the creation of Ryan Dahl is a simple, modern, and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust. As Deno 1.0.0 has released, there is much-awaited curiosity amongst developers around working with this new stack.</p>\n<p>When it comes to learning a new language, the first thing that comes to our mind is the creation of a todo app, supporting CRUD functionality. So here we will be creating a very simple Todo application using the Deno. </p>\n<p>So before starting I assume you have installed Deno on your system, if not then you can find the link <a href=\"/hello-world-deno/\">here</a>.\nFor the database, we will be using the <code>JSON</code> file as of now to completely focus on creating web API using Deno. Not more words and now let's start.</p>\n<p>The file structure we are going to follow is as below</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">  // Final directory structure</span>\n<span class=\"grvsc-line\">  deno-todo-api/</span>\n<span class=\"grvsc-line\">    --|controllers/</span>\n<span class=\"grvsc-line\">      |--|todo.ts</span>\n<span class=\"grvsc-line\">      |data/</span>\n<span class=\"grvsc-line\">      |--|todos.ts</span>\n<span class=\"grvsc-line\">      |interfaces/</span>\n<span class=\"grvsc-line\">      |--|Todo.ts</span>\n<span class=\"grvsc-line\">      |routes/</span>\n<span class=\"grvsc-line\">      |--|todo.ts</span>\n<span class=\"grvsc-line\">    --|server.ts</span>\n<span class=\"grvsc-line\">  </span></code></pre>\n<p>At any point in time, if you are stuck somewhere, you can follow this link to get the complete <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Deno/RestAPIWithDeno\">code</a>.</p>\n<ol>\n<li>Create a directory named <code>deno-todo-api</code> and move into that directory </li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">  mkdir deno-todo-api && cd deno-todo-api</span></code></pre>\n<ol start=\"2\">\n<li>Create the file <code>server.ts</code> in the root of the directory. </li>\n<li>Write the following code into the <code>server.ts</code> file to start a server</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Application</span><span class=\"mtk1\">, </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak@v17.1.4/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Application</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">port</span><span class=\"mtk1\">: </span><span class=\"mtk10\">number</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">8080</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Router</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">, ({ </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> }: { </span><span class=\"mtk12\">response</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\"> }) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Rest API tutorial with Deno&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">routes</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">allowedMethods</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;running on port &#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">port</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">port</span><span class=\"mtk1\"> });</span></span></code></pre>\n<p>Unlike <code>NodeJS</code> Deno does not need the <code>package.json</code> file for dependency management. Dependency management is simplified by having a list of modules and their respective URLs. </p>\n<p>Here we have used <a href=\"https://deno.land/x/oak\">oak</a>, a middleware framework for Deno's HTTP server, including a router middleware.</p>\n<ol start=\"4\">\n<li><code>server.ts</code> is the entry point for our web application. To check it run the following command in the root directory</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">deno run --allow-net server.ts</span></code></pre>\n<p>Open the browser and hit the URL <code>http://localhost:8080/</code></p>\n<p>You can see the following output in your browser</p>\n<p><img src=\"/a36b331956a234f26c49283ce04a1f31/output_localhost.webp\" alt=\"Browser output\"></p>\n<ol start=\"5\">\n<li>Now following the directory structure, we will create following folders in our project with the help of below command</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mkdir controllers data interfaces routes</span></code></pre>\n<ol start=\"6\">\n<li>First of all, we will create dummy data to play with our todo APIs.Go to the data folder and create a file called <code>todos.ts</code> and the following code into it</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"typescript\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">v4</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/std/uuid/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// interface</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Todo</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;../interfaces/Todo.ts&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">: </span><span class=\"mtk10\">Todo</span><span class=\"mtk1\">[] = [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">v4</span><span class=\"mtk1\">.</span><span class=\"mtk11\">generate</span><span class=\"mtk1\">(),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">task:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Hello world app with Deno&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">done:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">v4</span><span class=\"mtk1\">.</span><span class=\"mtk11\">generate</span><span class=\"mtk1\">(),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">task:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Simple Rest API with Deno&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">done:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">false</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>We will be using <code>v4</code>  provided by the <code>uuid</code> module to generate unique IDs.</p>\n<ol start=\"7\">\n<li>Now create a file in <code>interface/</code> folder <code>Todo.ts</code> and paste the following code. </li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"typescript\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">interface</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Todo</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">id</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">task</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">done</span><span class=\"mtk1\">: </span><span class=\"mtk10\">boolean</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>What are the interfaces??</p>\n<p>An interface defines the specifications of an entity. </p>\n<blockquote>\n<p>One of TypeScript’s core principles is that type checking focuses on the shape that values have. In TypeScript, interfaces fill the role of naming these types and are a powerful way of defining contracts within your code as well as contracts with code outside of your project.</p>\n</blockquote>\n<ol start=\"8\">\n<li>Now create a file named <code>todo.ts</code> in <code>controllers/</code> directory and paste the following code</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"typescript\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">v4</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/std/uuid/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// interfaces</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Todo</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../interfaces/Todo.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// stubs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todos</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../data/todos.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">getAll</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> ({ </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> }: { </span><span class=\"mtk12\">response</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\"> }) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">data:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todos</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">create</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    { </span><span class=\"mtk12\">request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> }: { </span><span class=\"mtk12\">request</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\">; </span><span class=\"mtk12\">response</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\"> },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (!</span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk12\">hasBody</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">400</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Please provide the task detail and  status&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">: </span><span class=\"mtk10\">Todo</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">v4</span><span class=\"mtk1\">.</span><span class=\"mtk11\">generate</span><span class=\"mtk1\">(),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">task:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">.</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">done:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">false</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = [...</span><span class=\"mtk12\">todos</span><span class=\"mtk1\">, </span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">data</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">getById</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    { </span><span class=\"mtk12\">params</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> }: { </span><span class=\"mtk12\">params</span><span class=\"mtk1\">: { </span><span class=\"mtk12\">id</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\"> }; </span><span class=\"mtk12\">response</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\"> },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todo</span><span class=\"mtk1\">: </span><span class=\"mtk10\">Todo</span><span class=\"mtk1\"> | </span><span class=\"mtk10\">undefined</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">.</span><span class=\"mtk11\">find</span><span class=\"mtk1\">((</span><span class=\"mtk12\">t</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">t</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\"> === </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (!</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">404</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;No task found related to given ID&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">data:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">update</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    { </span><span class=\"mtk12\">params</span><span class=\"mtk1\">, </span><span class=\"mtk12\">request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> }: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">params</span><span class=\"mtk1\">: { </span><span class=\"mtk12\">id</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\"> },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">request</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todo</span><span class=\"mtk1\">: </span><span class=\"mtk10\">Todo</span><span class=\"mtk1\"> | </span><span class=\"mtk10\">undefined</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">.</span><span class=\"mtk11\">find</span><span class=\"mtk1\">((</span><span class=\"mtk12\">t</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">t</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\"> === </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (!</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">404</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;No todo found&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">updatedData</span><span class=\"mtk1\">: { </span><span class=\"mtk12\">task</span><span class=\"mtk1\">?: </span><span class=\"mtk10\">string</span><span class=\"mtk1\">; </span><span class=\"mtk12\">done</span><span class=\"mtk1\">?: </span><span class=\"mtk10\">boolean</span><span class=\"mtk1\"> } = </span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">newTodos</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">((</span><span class=\"mtk12\">t</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">t</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\"> === </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\"> ? { ...</span><span class=\"mtk12\">t</span><span class=\"mtk1\">, ...</span><span class=\"mtk12\">updatedData</span><span class=\"mtk1\"> } : </span><span class=\"mtk12\">t</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">data:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">newTodos</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">delete</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    { </span><span class=\"mtk12\">params</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> }: { </span><span class=\"mtk12\">params</span><span class=\"mtk1\">: { </span><span class=\"mtk12\">id</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\"> }; </span><span class=\"mtk12\">response</span><span class=\"mtk1\">: </span><span class=\"mtk10\">any</span><span class=\"mtk1\"> },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">allTodos</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">.</span><span class=\"mtk11\">filter</span><span class=\"mtk1\">((</span><span class=\"mtk12\">t</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">t</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\"> !== </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">data:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">allTodos</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<ol start=\"9\">\n<li>Now go to <code>routes</code> and create <code>todo.ts</code> file in it and paste the following code </li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"typescript\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Router</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// controller</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todoController</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../controllers/todo.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/todos&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">todoController</span><span class=\"mtk1\">.</span><span class=\"mtk12\">getAll</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/todos&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">todoController</span><span class=\"mtk1\">.</span><span class=\"mtk12\">create</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/todos/:id&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">todoController</span><span class=\"mtk1\">.</span><span class=\"mtk12\">getById</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">put</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/todos/:id&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">todoController</span><span class=\"mtk1\">.</span><span class=\"mtk12\">update</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/todos/:id&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">todoController</span><span class=\"mtk1\">.</span><span class=\"mtk12\">delete</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\">;</span></span></code></pre>\n<ol start=\"10\">\n<li>Now since we have created the complete MVC project for our todo APIs, we will be going to update our main <code>server.ts</code> file with following code</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"typescript\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Application</span><span class=\"mtk1\">, </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todoRouter</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./routes/todo.ts&quot;</span><span class=\"mtk1\">; </span><span class=\"mtk3\">// added the router call</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Application</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">port</span><span class=\"mtk1\">: </span><span class=\"mtk10\">number</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">8080</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">todoRouter</span><span class=\"mtk1\">.</span><span class=\"mtk11\">routes</span><span class=\"mtk1\">()); </span><span class=\"mtk3\">// Intitialize the router with our application. </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">todoRouter</span><span class=\"mtk1\">.</span><span class=\"mtk11\">allowedMethods</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;listen&quot;</span><span class=\"mtk1\">, ({ </span><span class=\"mtk12\">secure</span><span class=\"mtk1\">, </span><span class=\"mtk12\">hostname</span><span class=\"mtk1\">, </span><span class=\"mtk12\">port</span><span class=\"mtk1\"> }) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">protocol</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">secure</span><span class=\"mtk1\"> ? </span><span class=\"mtk8\">&quot;https://&quot;</span><span class=\"mtk1\"> : </span><span class=\"mtk8\">&quot;http://&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">url</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">`</span><span class=\"mtk4\">${</span><span class=\"mtk12\">protocol</span><span class=\"mtk4\">}${</span><span class=\"mtk12\">hostname</span><span class=\"mtk1\"> ?? </span><span class=\"mtk8\">&quot;localhost&quot;</span><span class=\"mtk1\">}:</span><span class=\"mtk12\">$</span><span class=\"mtk1\">{</span><span class=\"mtk12\">port</span><span class=\"mtk1\">}</span><span class=\"mtk8\">`;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">  console.log(`</span><span class=\"mtk12\">Listening</span><span class=\"mtk1\"> </span><span class=\"mtk12\">on</span><span class=\"mtk1\">: </span><span class=\"mtk12\">$</span><span class=\"mtk1\">{</span><span class=\"mtk12\">port</span><span class=\"mtk1\">}</span><span class=\"mtk8\">`);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">await app.listen({ port });</span></span></code></pre>\n<ol start=\"11\">\n<li>Now run again the server with the following command </li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">deno run --allow-net server.ts</span></code></pre>\n<p>Now open the postman and hit the get URL <code>http://localhost:8080/todos/</code></p>\n<p><img src=\"/5d4cd381f56310b0117435ea3cc06296/all_output.webp\" alt=\"Browser output\"></p>\n<p>To check the getByID router, copy the ID of any task and hit the URL like </p>\n<p><code>http://localhost:8080/todos/:id</code></p>\n<p>You will be getting output like below </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;data&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">&quot;id&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;eeacacdc-e55b-4299-aab7-5f631a2e3975&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">&quot;task&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Hello world app with Deno&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">&quot;done&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">true</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Similarly, we can verify the complete crud API created. Below is the reference of all APIs created in the blog post</p>\n<table>\n<thead>\n<tr>\n<th>API</th>\n<th>Method</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>http://localhost:8080/todos/</code></td>\n<td>GET</td>\n<td>Fetch All todos</td>\n</tr>\n<tr>\n<td><code>http://localhost:8080/todos/{id}</code></td>\n<td>GET</td>\n<td>Fetch todo by ID</td>\n</tr>\n<tr>\n<td><code>http://localhost:8080/todos/</code></td>\n<td>POST</td>\n<td>Create New todo</td>\n</tr>\n<tr>\n<td><code>http://localhost:8080/todos/{id}</code></td>\n<td>PUT</td>\n<td>Update todo by ID</td>\n</tr>\n<tr>\n<td><code>http://localhost:8080/todos/{id}</code></td>\n<td>DELETE</td>\n<td>Delete todo by ID</td>\n</tr>\n</tbody>\n</table>\n<p>You can find the complete code of the repo <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Deno/RestAPIWithDeno\">here</a> </p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n</style>","frontmatter":{"date":"June 08, 2020","updated_date":null,"title":"Create REST API using deno ","tags":["Deno","REST","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7699115044247788,"src":"/static/4a65a81c1ab5e2211f19e9aeeb888f6b/58556/task.webp","srcSet":"/static/4a65a81c1ab5e2211f19e9aeeb888f6b/61e93/task.webp 200w,\n/static/4a65a81c1ab5e2211f19e9aeeb888f6b/1f5c5/task.webp 400w,\n/static/4a65a81c1ab5e2211f19e9aeeb888f6b/58556/task.webp 800w,\n/static/4a65a81c1ab5e2211f19e9aeeb888f6b/99238/task.webp 1200w,\n/static/4a65a81c1ab5e2211f19e9aeeb888f6b/135cd/task.webp 1280w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Aman Agrawal","github":"aman-agrwl","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/understanding-jsonp/"},"html":"<p>Nowadays, many API providers support JSONP requests. One reason for this is that most web browsers disable cross-domain requests when using basic Ajax.</p>\n<p>For example, if your website has the domain \"a.com\", it will use JavaScript hosted on a.com. When the a.com JavaScript makes an Ajax call to make a request on b.com, most web browsers would automatically deem the Ajax call as insecure and disable it. This is called the Same-Origin Policy and web browsers have this to prevent malicious scripts from sending off information to a different domain. Because you need the a.com JavaScript to access b.com to provide your service, this seems to pose a pretty big issue … JSONP to the rescue!</p>\n<p>Before understanding JSONP, we already know JSON is an object notation of JavaScript. The \"P\" stands for padding. So it’s a padded JSON, and, to be more specific, the JSON object is padded with a JavaScript function! It looks like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">jsFunction</span><span class=\"mtk1\">({</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk12\"> :</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Ash Ketchum&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;role&quot;</span><span class=\"mtk12\"> :</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Pokemon trainer&quot;</span><span class=\"mtk1\">});</span></span></code></pre>\n<p>Thus, technically, any call that retrieves JSONP, sends off an executable JavaScript line, if and only if your page has a JavaScript function that has the same function name that’s returned in the JSONP!</p>\n<p>Let’s look at an example: say the user is on a.com and the browser is using JavaScript hosted on a.com. Then I shouldn't have any issues making Ajax calls to a.com. Ajax GET requests to b.com however, would fail. To avoid this, I first create a method in the JavaScript code that's located on a.com with the following signature</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">getData</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// use this data</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>With this, an Ajax call using JSONP will pass through fine and return this data:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">getData</span><span class=\"mtk1\">({</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk12\"> :</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;test&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk12\"> :</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;test Value&quot;</span><span class=\"mtk1\">});</span></span></code></pre>\n<p>After processing the request, the web browser will call the \"getData\" function because whenever a JavaScript tag is loaded, it gets executed.</p>\n<p>Now, the JSON object will get passed as an argument to the getData function as the data parameter. So, you can think of the getData as a callback method of the request.</p>\n<p>You can see the below code clearly</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">addJavascriptFile</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">url</span><span class=\"mtk1\">, </span><span class=\"mtk12\">context</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">context</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">context</span><span class=\"mtk1\"> || </span><span class=\"mtk12\">document</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">head</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">context</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementsByTagName</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;head&#39;</span><span class=\"mtk1\">)\\[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">\\];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">js</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">context</span><span class=\"mtk1\">.</span><span class=\"mtk11\">createElement</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;script&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">js</span><span class=\"mtk1\">.</span><span class=\"mtk12\">src</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">url</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">js</span><span class=\"mtk1\">.</span><span class=\"mtk12\">type</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;text/JavaScript&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">head</span><span class=\"mtk1\">.</span><span class=\"mtk11\">appendChild</span><span class=\"mtk1\">(</span><span class=\"mtk12\">js</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">js</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">getJsonp</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">url</span><span class=\"mtk1\">, </span><span class=\"mtk12\">handle</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//creating random name of function as to not conflict with others</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">func</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;jsonpCallback&#39;</span><span class=\"mtk1\"> + </span><span class=\"mtk10\">Math</span><span class=\"mtk1\">.</span><span class=\"mtk11\">floor</span><span class=\"mtk1\">((</span><span class=\"mtk10\">Math</span><span class=\"mtk1\">.</span><span class=\"mtk11\">random</span><span class=\"mtk1\">() \\* </span><span class=\"mtk7\">1000000000000000000</span><span class=\"mtk1\">) + </span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//adding randomly created function to global window object</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">window</span><span class=\"mtk1\">\\[</span><span class=\"mtk12\">func</span><span class=\"mtk1\">\\] = </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">data</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//calling handle</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">handle</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//removing random named declared function</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">window</span><span class=\"mtk1\">\\[</span><span class=\"mtk12\">func</span><span class=\"mtk1\">\\] = </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> () {};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//removing added js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk12\">head</span><span class=\"mtk1\">.</span><span class=\"mtk11\">removeChild</span><span class=\"mtk1\">(</span><span class=\"mtk12\">js</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//manipulating and adding js file to head</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">endurl</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">url</span><span class=\"mtk1\">.</span><span class=\"mtk11\">indexOf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;?&#39;</span><span class=\"mtk1\">) != -</span><span class=\"mtk7\">1</span><span class=\"mtk1\"> ? </span><span class=\"mtk12\">url</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&#39;&amp;amp;callback=&#39;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">func</span><span class=\"mtk1\"> : </span><span class=\"mtk12\">url</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&#39;?callback=&#39;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">func</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">js</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">addJavascriptFile</span><span class=\"mtk1\">(</span><span class=\"mtk12\">endurl</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The above code is not doing any magic, it will accept the URL of the API and add a parameter callback with a random name, and also create a global method with this same random name. It will then create a script tag and add the complete URL to src of this tag.</p>\n<p>The API will read the callback parameter from the query string and, if the callback parameter has the value \"jsonCallback\", the response will be as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">jsonpCallback</span><span class=\"mtk1\">({</span><span class=\"mtk8\">&quot;name&quot;</span><span class=\"mtk12\"> :</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;test&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk12\"> :</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;test Value&quot;</span><span class=\"mtk1\">});</span></span></code></pre>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"June 29, 2018","updated_date":null,"title":"Understanding JSONP","tags":["JavaScript","JSONP","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.834862385321101,"src":"/static/85e9390b35cfcd06b4e455bd05cc8ea7/50fff/Screenshot-2018-06-29-12.21.27.webp","srcSet":"/static/85e9390b35cfcd06b4e455bd05cc8ea7/61e93/Screenshot-2018-06-29-12.21.27.webp 200w,\n/static/85e9390b35cfcd06b4e455bd05cc8ea7/1f5c5/Screenshot-2018-06-29-12.21.27.webp 400w,\n/static/85e9390b35cfcd06b4e455bd05cc8ea7/50fff/Screenshot-2018-06-29-12.21.27.webp 730w","sizes":"(max-width: 730px) 100vw, 730px"}}},"author":{"id":"Rakesh Soni","github":"oyesoni","avatar":"rakesh-soni.webp"}}}},{"node":{"fields":{"slug":"/engineering/what-is-an-api/"},"html":"<p>An API is an acronym for Application Programming Interface. API's include various tools, protocols, and routines. API's are used as a way for applications to communicate with various systems.</p>\n<p>But what does this mean? Well let me explain what they are with some examples. I am going to be using various API's for these examples.</p>\n<p><strong>Let's Begin</strong></p>\n<p>Let's start by looking at a favorite website of mine called The Yoda Speak Generator found <a href=\"https://lingojam.com/EnglishtoYoda\">here</a>.</p>\n<p>This website allows users to enter text and get a return of that same text formatted the way Yoda might say it. This is done with an API.</p>\n<p>Yoda Speak: Fun stuff, api's are! Yes, hmmm.</p>\n<p>API’s contain what is called an endpoint to access this API. The endpoint provides the connection to communicate with the API and give it some text to generate into Yoda Speak. The API would then return the generated Yoda Speak to the location of the request.</p>\n<p>Another way to think of an API is to think of it like an egg carton. An egg carton holds the eggs, protects them from damage and allows someone who wants to make breakfast a way to open and close the carton to access the eggs inside. The eggs inside would be the data, and the hand reaching into the carton would be much like the communication using an endpoint from a server.</p>\n<p>Okay, Let's make breakfast.... Just Kidding!</p>\n<p>For those of you who are visual Let's look at some examples of the code. These snippets are in PHP because it is my favorite language. Below is a link to download a small zip file called apidemo.zip.</p>\n<p>Demo Link</p>\n<p>You can host this directory on your localhost or on a website if you choose.</p>\n<p>After you have extracted the zip and have a directory such as localhost/apidemo open a browser and enter <code>http://localhost/apidemo/api.php?request=example&#x26;name=yourname</code> where localhost is your domain.</p>\n<p>To enter this endpoint in an application that makes API calls try Postman. Here is a <a href=\"http://www.getpostman.com/\">link</a> for a chrome extension.</p>\n<p>Try using a GET and a POST method with parameters request=example for the example function in api.php and name=yourname to output a name</p>\n<p>You should now see the output \"Your name is yourname\" in your browser</p>\n<p>explore the files api.php, API.class.php and MyAPI.php to explore how this simple API is taking in the parameters and outputting a name</p>\n<p>Hopefully, I have explained API's so you have a basic understanding of what they are. There are many types of API's, one that you may see often is RESTful API's, these unlike this example must abide by constraints that have been defined by the REST architecture.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"June 23, 2015","updated_date":null,"title":"What is an API","tags":["API","Postman"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/a01dd1d7515afffa79ea80811d70b895/403a4/whats-an-api-300x300.webp","srcSet":"/static/a01dd1d7515afffa79ea80811d70b895/61e93/whats-an-api-300x300.webp 200w,\n/static/a01dd1d7515afffa79ea80811d70b895/403a4/whats-an-api-300x300.webp 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Zoie Carnegie","github":null,"avatar":null}}}}]}},"pageContext":{"tag":"API"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}