<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bervianto Leo's Stories]]></title><description><![CDATA[Compiled Stories from Bervianto Leo Pratama]]></description><link>https://hashnode.berviantoleo.my.id</link><generator>RSS for Node</generator><lastBuildDate>Sun, 17 May 2026 06:24:00 GMT</lastBuildDate><atom:link href="https://hashnode.berviantoleo.my.id/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why should we read Azure Security?]]></title><description><![CDATA[During my last two weeks, I read the Azure Security MEAP version. The Azure Security book is authored by Bojan Magusic. From the Manning page, Bojan Magusic is a Program Manager with Microsoft on the Cloud Security Customer Experience Engineering Tea...]]></description><link>https://hashnode.berviantoleo.my.id/why-should-we-read-azure-security</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/why-should-we-read-azure-security</guid><category><![CDATA[Azure]]></category><category><![CDATA[azure-security]]></category><category><![CDATA[ebook]]></category><category><![CDATA[ebooks]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Thu, 04 May 2023 12:49:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KPZNNKQbTMw/upload/763f1791f2aa8cc61ed44f2a423d4a32.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>During my last two weeks, I read the Azure Security MEAP version. The Azure Security book is authored by Bojan Magusic. From the Manning page, Bojan Magusic is a Program Manager with Microsoft on the Cloud Security Customer Experience Engineering Team. My first impression reading this book is that book explains clearly each security aspect that we need to be considered when building and securing Azure applications. Although the main page says, "For software and security engineers", I think this book is beginners friendly because it provides illustration which helps me to understand the concepts.</p>
<p>More information about MEAP. Please check <a target="_blank" href="https://www.manning.com/meap-program">here</a>.</p>
<h2 id="heading-reading-azure-security-using-livebook-in-manning">Reading Azure Security using liveBook in Manning</h2>
<p>I'm choosing to read in <a target="_blank" href="https://livebook.manning.com">liveBook</a> because the liveBook gives me a great reading experience. Anyway, it also provides other formats, such as pdf, epub, and Kindle if you prefer using offline versions. You don't need to worry about the updated versions. You can download the newest version whenever getting updates.</p>
<p>The liveBook allows you to highlight, bookmark, take notes, create discussion, and give feedback about the book content. Those features give you the same experiences when you read on a PDF reader, but it might be better than a PDF reader.</p>
<h2 id="heading-what-is-the-azure-security">What is the Azure Security?</h2>
<p>I am amazed when reading this book, Azure Security. I thought I would be puzzled by technical things and security concepts. But I was wrong! The book gives good illustrations of security concepts. However, it's also balanced between concepts and technical aspects. I can follow the detailed steps and do some hands-on following the books.</p>
<p>This book, Azure Security, has eleven chapters (when I'm writing this post, the book has nine chapters). Each chapter provides a good structure and is well explained. This book has three parts. The first part will give us the fundamental concepts of Azure security. The second part will take us deep into each security aspect of Azure resources. Lastly, we can get more ideas on how to strengthen the security of Azure applications.</p>
<h2 id="heading-why-do-i-like-the-azure-security">Why do I like the Azure Security?</h2>
<p>I get some benefits from the Azure Security books. Those benefits are:</p>
<ol>
<li><p>Azure security aspects in the book are up to date. I like how the books bring us the best concepts and provide the newest product knowledge.</p>
</li>
<li><p>Providing good structures and clear steps for each hands-on to secure the Azure resources.</p>
</li>
<li><p>Easy to read the explanation for complex concepts. Well explained with illustrations that help us to understand.</p>
</li>
<li><p>I love section 4, which covers Azure App Service and Kubernetes, which I use daily. I also love section 5, which covers encryption, great to use in our Azure applications.</p>
</li>
</ol>
<h2 id="heading-why-should-you-read-azure-security">Why should you read Azure Security?</h2>
<p>I hope you also get the benefits same as me. You can use the liveBook or the offline version like pdf. The completeness of this book will give you a great experience for securing your Azure resources. I'm looking forward to your excitement about this book.</p>
<p><img src="https://media.giphy.com/media/13CfqebsPMctjO/giphy.gif" alt class="image--center mx-auto" /></p>
<hr />
<p>I have good news for you! You can use the 35% discount code (good for all our products in all formats): <strong>blberv23</strong></p>
<p>Please refer to the following link: <a target="_blank" href="http://mng.bz/6DYe">http://mng.bz/6DYe</a> or scan the QR code below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683204026705/cc449e91-c10c-42dc-9fec-0f65f8006de5.png?height=250" alt="QR Code" class="image--center mx-auto" /></p>
<p>You can use the limited 3 x free eBook codes for <a target="_blank" href="https://www.manning.com/books/azure-security-2">Azure Security</a>:</p>
<p><strong>bsbvaz-7B36<br />bsbvaz-6753<br />bsbvaz-409D</strong></p>
<p><strong>How to redeem single-use coupon codes</strong></p>
<p>If you don't have a Manning account, you should create <a target="_blank" href="https://www.manning.com/">one</a>. All orders MUST include a valid email address.</p>
<p>Single-use coupons may be redeemed only once and eBooks are delivered immediately.</p>
<p>&gt;&gt; Book's product page: <a target="_blank" href="https://www.manning.com/books/azure-security-2">https://www.manning.com/books/azure-security-2</a></p>
<ol>
<li><p>Select “eBook: pdf + ePub + kindle + liveBook.”</p>
</li>
<li><p>Click “Add to Cart.”</p>
</li>
<li><p>Click “Go to Cart.”</p>
</li>
<li><p>Enter your single-use coupon code</p>
</li>
<li><p>Click “Apply.”</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Migrating My Portfolio Web to AWS Amplify (Part 1)]]></title><description><![CDATA[After some decades, I decided to reactivate my old project to use React for My Portfolio Website. My current website uses Vue.js, and you can access it here.
I want to migrate the portfolio step by step.

Create React Project for My Portfolio Web (st...]]></description><link>https://hashnode.berviantoleo.my.id/migrating-my-portfolio-web-to-aws-amplify-part-1</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/migrating-my-portfolio-web-to-aws-amplify-part-1</guid><category><![CDATA[AWS]]></category><category><![CDATA[AWS Amplify]]></category><category><![CDATA[portfoliowebsite]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Wed, 12 Apr 2023 17:53:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/iDkiP2GXlR8/upload/7c671fa9b4a9a8abafba3fcea9964c77.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After some decades, I decided to reactivate my old project to use React for My Portfolio Website. My current website uses Vue.js, and you can access it <a target="_blank" href="https://berviantoleo.my.id">here</a>.</p>
<p>I want to migrate the portfolio step by step.</p>
<ol>
<li><p>Create React Project for My Portfolio Web (static web) and host it in AWS Amplify.</p>
</li>
<li><p>Prepare the backend using AWS Amplify and migrate my CMS Admin. In short, you can check the project <a target="_blank" href="https://github.com/bervProject/MyPersonalWebAdmin">here</a>. I will continue the project in the next part.</p>
</li>
<li><p>Connect the data with the React Project.</p>
</li>
</ol>
<p>You can see these images for more information about my migration steps.</p>
<ul>
<li>Step 1</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681323407304/c991602c-0e7c-40d7-99c5-0a97f48c2d1c.png" alt="Step 1" class="image--center mx-auto" /></p>
<ul>
<li>Step 2</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681323508730/8d07e897-9e51-4ceb-968d-f454f2573345.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Step 3</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681323519615/81ba36fc-1d24-43f8-9b7f-9b8ea31dfdb4.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-what-is-aws-amplify">What is AWS Amplify?</h2>
<p>From my perspective as a Software Engineer or Backend Engineer, this is a tool that helps me to deliver Fullstack Applications into AWS quickly, easily, and user-friendly! Imagine if you need to understand the infrastructure, the delivery pipelines, etc. You might be overthinking about the cloud especially AWS when you want to start hosting your existing website or your initial website. I want to show you how I start using AWS Amplify, but it doesn't mean I use the best practices. Please refer to the documentation for the best practices using AWS Amplify.</p>
<h2 id="heading-lets-get-started">Let's Get Started</h2>
<ol>
<li><p>Install <a target="_blank" href="https://docs.amplify.aws/cli/">Amplify CLI</a>.</p>
</li>
<li><p>Because I'm using yarn, please <a target="_blank" href="https://classic.yarnpkg.com/lang/en/docs/install/#windows-stable">prepare</a> the yarn.</p>
</li>
<li><p><a target="_blank" href="https://docs.amplify.aws/start/getting-started/setup/q/integration/react/">Set up</a> the backend part for React.js.</p>
<ol>
<li><p><code>amplify init</code> - Configure my project to connect with AWS Amplify.</p>
</li>
<li><p><code>yarn add @aws-amplify/ui-react aws-amplify</code> - Add the AWS Amplify library and AWS Amplify UI library to my React project. For more details about the UI library, you can check <a target="_blank" href="https://ui.docs.amplify.aws/react/getting-started/introduction">here</a>.</p>
</li>
</ol>
</li>
</ol>
<h2 id="heading-my-process">My Process</h2>
<ol>
<li><p>Coding, of course. I won't share the detailed steps. In short, here are my dependencies,</p>
<ol>
<li><p>React Router 6.10.0 - Frontend Routing</p>
</li>
<li><p>aws-amplify 5.0.25 - Will be used for connecting/gathering the data from the backend</p>
</li>
<li><p>@aws-amplify/ui-react 4.6.0 - UI Library</p>
</li>
<li><p>React 18.2.0</p>
</li>
<li><p>React Redux 8.0.5 - Handle theme state</p>
</li>
<li><p>@reduxjs/toolkit 1.9.3</p>
</li>
</ol>
</li>
<li><p>I just created the home page. I will move the pages one by one. So, some pages will refer to my previous website.</p>
</li>
<li><p>Add hosting: <code>amplify hosting add</code></p>
<ol>
<li><p>Currently, I use manual deployment. However, I will consider using automatic deployment.</p>
</li>
<li><p>Try build: <code>yarn build</code></p>
</li>
<li><p>For more information about hosting, please check <a target="_blank" href="https://docs.amplify.aws/cli/hosting/hosting/">here</a>.</p>
</li>
</ol>
</li>
<li><p>Sending PR</p>
<ol>
<li>Please check <a target="_blank" href="https://github.com/bervProject/my-personal-web-react/pull/701">here</a> my PR and the changes.</li>
</ol>
</li>
<li><p>Merge PR and prepare to publish manually.</p>
<ol>
<li>Publish manually: <code>amplify publish</code></li>
</ol>
</li>
<li><p>My website is ready! Here is the link: <a target="_blank" href="https://dev.d2te8gdj4pjzkk.amplifyapp.com">https://dev.d2te8gdj4pjzkk.amplifyapp.com</a></p>
</li>
</ol>
<h2 id="heading-lesson-learned">Lesson Learned</h2>
<p>It's quite easy to deploy a static website from React! I'm planning to have the backend using AWS Amplify and connect the admin website within it. Of course, the admin website will be hosted in AWS using AWS Amplify!</p>
<p>Please bear with me because I'm so bad at Front-End and Design. Here is a screenshot of my website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681321477605/ad448358-429f-45bc-92b7-99d3b1fb989f.png" alt class="image--center mx-auto" /></p>
<p><strong>Note:</strong></p>
<ul>
<li>Don't forget to add the redirect! <a target="_blank" href="https://docs.aws.amazon.com/amplify/latest/userguide/redirects.html#redirects-for-single-page-web-apps-spa">Documentation</a>.</li>
</ul>
<p>Yey! My previous project is alive now! I will continue in the next part. So, stay tuned!</p>
<hr />
<h2 id="heading-my-repository">My Repository</h2>
<p><a target="_blank" href="https://github.com/bervProject/my-personal-web-react">https://github.com/bervProject/my-personal-web-react</a></p>
<h2 id="heading-thank-you">Thank you!</h2>
<p><a target="_blank" href="https://giphy.com/gifs/theoffice-ZfK4cXKJTTay1Ava29"><img src="https://media.giphy.com/media/ZfK4cXKJTTay1Ava29/giphy.gif" alt="Thank you GIF" class="image--center mx-auto" /></a></p>
]]></content:encoded></item><item><title><![CDATA[Case Study: Connecting Azure AD SSO with AWS]]></title><description><![CDATA[Introduction
We will learn how to connect Azure AD with AWS. We will use Azure AD as the identity provider, so Azure AD users will be used to log in to AWS. Let's dive deep into each component.
Azure AD
I will not explain too much about Azure AD. I'l...]]></description><link>https://hashnode.berviantoleo.my.id/case-study-connecting-azure-ad-sso-with-aws</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/case-study-connecting-azure-ad-sso-with-aws</guid><category><![CDATA[AWS]]></category><category><![CDATA[AzureAD]]></category><category><![CDATA[SSO]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Sat, 19 Nov 2022 07:00:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840724674/FzfOycGUX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>We will learn how to connect Azure AD with AWS. We will use Azure AD as the identity provider, so Azure AD users will be used to log in to AWS. Let's dive deep into each component.</p>
<h2 id="heading-azure-ad">Azure AD</h2>
<p>I will not explain too much about Azure AD. I'll recommend reading <a target="_blank" href="https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis">the documentation</a> and <a target="_blank" href="https://azure.microsoft.com/en-us/products/active-directory/">the home page of the Azure AD</a>. In short, Azure AD (Azure Active Directory) is a cloud-based identity and access management service. You can use the identity provided by Azure AD for connecting various applications or services, including AWS. If you want to learn more about Azure AD, please visit the documentation.</p>
<h2 id="heading-azure-ad-sso-with-aws">Azure AD SSO with AWS</h2>
<p>For connecting Azure AD with AWS, we will need an Enterprise Application. Azure AD has an application gallery to provide a "template" for connecting Azure AD with another SaaS (Software as a Service). Application gallery will help us to create the Enterprise Application, and we can configure the Enterprise Application for <a target="_blank" href="https://learn.microsoft.com/en-us/azure/active-directory/develop/single-sign-on-saml-protocol">single sign-on (SSO)</a> and <a target="_blank" href="https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/user-provisioning">automated user provisioning</a>. If you want to know more about the application gallery, you might need to read <a target="_blank" href="https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/overview-application-gallery">this documentation</a>. But in this post, we will learn to set up the Enterprise Application and configure it for SSO.</p>
<p>We have two approaches to setting up the Enterprise Application. First, we use single AWS Apps to connect multiple AWS Accounts. Last, we create an AWS app for each AWS account.</p>
<h3 id="heading-single-aws-apps">Single AWS Apps</h3>
<p>Single AWS Apps is a model to centralize the configuration, and we only use one Enterprise App to connect multiple AWS Accounts. You will need this approach if you have a small amount of AWS Accounts and roles. We can't configure many AWS Accounts because there is a limitation for the manifest. In contrast, you will need Multiple AWS Apps for the case of large numbers of AWS Accounts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840705497/NsHC6pYgJ.png" alt="Single AWS App" /></p>
<h3 id="heading-multiple-aws-apps">Multiple AWS Apps</h3>
<p>Multiple AWS Apps is a model to map each AWS Account into one AWS Apps. The disadvantage of this model is we need to manage many apps and monitor each app. Other than that, we need to automate of each process to minimize wrong configurations.</p>
<p>Do you imagine how we update the signing certificate for 100 AWS Accounts manually? You will quickly be exhausted and upload the wrong configuration. After that, the SSO doesn't work.</p>
<p>It will become a nightmare if we can't automate the configuration. We are using MS Graph SDK and AWS SDK to solve that problem.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840706731/PDA9OZ5br.png" alt="Multiple AWS App" /></p>
<h3 id="heading-flow">Flow</h3>
<h4 id="heading-tldr">TLDR</h4>
<p>In general, you only need to configure the Enterprise App, download the XML from the Enterprise App, upload the XML to AWS Identity Provider, and configure the roles to use the Identity Provider.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840708042/hsNhlICMt.png" alt="tldr flow" /></p>
<h4 id="heading-flow-in-technical-term">Flow in Technical Term</h4>
<p>You might need to see this diagram for details in technical terms.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840709655/d9kBKGD6B.png" alt="technical" /></p>
<h2 id="heading-repositories">Repositories</h2>
<p>Feel free to check this repository of my project. Please give feedback about this project because this project doesn't fully automate. I plan to have a "save" state and validation of the existing Enterprise App. Currently, the project is assumed to create a new Enterprise App.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/bervProject/AzureADxAWSIntegrator">https://github.com/bervProject/AzureADxAWSIntegrator</a></div>
<h2 id="heading-project-details">Project Details</h2>
<p>I use .NET as the main programming language. You can use different languages if you are more familiar with them as long as it's supported by the SDK/library.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840711877/kTSDlOX3o.png" alt="General View" /></p>
<p>I have 3 projects in this repository. The first project is responsible to connect with Microsoft Graph API. The second one is responsible to connect with AWS API. The last one is responsible to manage the business flow to connect both projects.</p>
<h3 id="heading-azure-integrator">Azure Integrator</h3>
<p>Please see this diagram for the full steps of the Azure Integrator project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840713452/9Dbz7LGrC.png" alt="Azure Integrator" /></p>
<h3 id="heading-aws-integrator">AWS Integrator</h3>
<p>Please see this diagram for the full steps of the AWS Integrator project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840715538/BCv9ZoL27.png" alt="AWS Integrator" /></p>
<hr />
<p>For more details, please refer to the documentation in the repository. I will keep the project up to date.</p>
<h2 id="heading-testing-the-sso">Testing the SSO</h2>
<ol>
<li><p>Go to the <a target="_blank" href="https://myapps.microsoft.com">myapps.microsoft.com</a>. Click the AWS Icon.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840717400/_CffFcQRh.png" alt="My Apps" /></p>
</li>
<li><p>You will be redirected to AWS Dashboard. Please make sure your role and username are correct.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840718808/vqaU4EC6Q.png" alt="AWS Dashboard" /></p>
</li>
<li><p>On my side, my account is allowed to see the EC2 instances. You can configure the role based on your needs.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840721470/FhA_8MxGu.png" alt="ec2" /></p>
</li>
</ol>
<h2 id="heading-thank-you">Thank you</h2>
<p>Thank you for reading. Feel free to give feedback for the process, project and this post.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668840723449/fL2OOXa1s.gif" alt="Thanks" /></p>
<h2 id="heading-references">References</h2>
<h3 id="heading-main-resources">Main Resources</h3>
<h4 id="heading-azure-ad-aad">Azure AD (AAD)</h4>
<ul>
<li><a target="_blank" href="https://learn.microsoft.com/en-us/graph/application-saml-sso-configure-api?tabs=csharp">Tutorials/Documentations from Microsoft</a></li>
<li>Permissions <code>Application.ReadWrite.All</code>, <code>AppRoleAssignment.ReadWrite.All</code>, <code>Policy.Read.All</code>, <code>Policy.ReadWrite.ApplicationConfiguration</code>, and <code>User.ReadWrite.All</code>.</li>
<li><a target="_blank" href="https://myapps.microsoft.com/">App List Dashboard</a></li>
</ul>
<h4 id="heading-aws">AWS</h4>
<ul>
<li><a target="_blank" href="https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/quick-start-s3-1-cross.html">Simple cross-platform application using the AWS SDK for .NET</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/IAM/TIAMServiceClient.html">AmazonIdentityManagementServiceClient</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/IAM/MIAMServiceCreateSAMLProviderCreateSAMLProviderRequest.html">AmazonIdentityManagementServiceClient.CreateSAMLProvider</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/IAM/MIAMServiceAttachRolePolicyAttachRolePolicyRequest.html">AmazonIdentityManagementServiceClient.AttachRolePolicy</a></li>
<li><a target="_blank" href="https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/IAM/MIAMServiceCreatePolicyCreatePolicyRequest.html">AmazonIdentityManagementServiceClient.CreatePolicy</a></li>
</ul>
<h3 id="heading-setup-sso-manually-single-account">Setup SSO Manually - Single Account</h3>
<ul>
<li>https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/amazon-web-service-tutorial</li>
</ul>
<h3 id="heading-setup-sso-manually-multiple-accounts">Setup SSO Manually - Multiple Accounts</h3>
<ul>
<li>https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/aws-multi-accounts-tutorial</li>
</ul>
<h3 id="heading-another-topic-provisioning">Another Topic - Provisioning</h3>
<ul>
<li>https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/application-provisioning-configuration-api</li>
</ul>
<h3 id="heading-another-code-samples">Another Code Samples</h3>
<ul>
<li>https://learn.microsoft.com/en-us/samples/azure-samples/ms-identity-dotnetcore-galleryapp-management/automate-saml-based-sso-app-configuration-using-ms-graph-api-sdk-net/</li>
</ul>
<h3 id="heading-toolssdk-documentation">Tools/SDK Documentation</h3>
<ul>
<li><a target="_blank" href="https://learn.microsoft.com/en-us/graph/sdks/create-client?tabs=CS">Microsoft Graph Client</a></li>
<li><a target="_blank" href="https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS#client-credentials-provider">Authentication Provider for MS Graph</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Forum Web App - AWS Amplify]]></title><description><![CDATA[Will always work on progress and keep updated! :D

Repository
https://github.com/bervProject/MyForumAmplify
URL
https://main.d1rdvijeud51fr.amplifyapp.com/
Want to try?
You can try to register. I don't limit the registration, feel free to test.
Backg...]]></description><link>https://hashnode.berviantoleo.my.id/forum-web-app-aws-amplify</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/forum-web-app-aws-amplify</guid><category><![CDATA[AWS Amplify]]></category><category><![CDATA[AWS Amplify Hackathon]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Tue, 27 Sep 2022 13:34:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664280701685/fdh2vqFtB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Will always work on progress and keep updated! :D</p>
</blockquote>
<h2 id="heading-repository">Repository</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/bervProject/MyForumAmplify">https://github.com/bervProject/MyForumAmplify</a></div>
<h2 id="heading-url">URL</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://main.d1rdvijeud51fr.amplifyapp.com/">https://main.d1rdvijeud51fr.amplifyapp.com/</a></div>
<h2 id="heading-want-to-try">Want to try?</h2>
<p>You can try to register. I don't limit the registration, feel free to test.</p>
<h2 id="heading-background">Background</h2>
<p>I do coding as my hobby. I really love to try and use AWS Services since most of the services are customer friendly. I want to build a forum app to collaborate with excellent software engineers or developers and I like how they post some articles to give some best practices.</p>
<p>I just want to connect with each other and share as caring.</p>
<h2 id="heading-how-i-built-this">How I Built This?</h2>
<h3 id="heading-install-the-cli-andamp-setup-your-aws-account">Install the CLI &amp; Setup Your AWS Account</h3>
<pre><code class="lang-bash">npm install -g @aws-amplify/cli
</code></pre>
<p><img src="https://docs.amplify.aws/start/getting-started/installation/q/integration/react/#option-1-watch-the-video-guide" alt="More information" /></p>
<h3 id="heading-generate-the-ui-project">Generate the UI Project</h3>
<pre><code class="lang-bash">npx create-react-app myforumamplify
</code></pre>
<h3 id="heading-generate-backend-amplify-configuration-andamp-install-amplify-library">Generate Backend Amplify Configuration &amp; Install Amplify Library</h3>
<p><a target="_blank" href="https://docs.amplify.aws/start/getting-started/setup/q/integration/react/#install-amplify-libraries">Reference</a></p>
<h2 id="heading-setup-authentication-in-aws-amplify-studio">Setup Authentication in AWS Amplify Studio</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1664281548995/prOtKDwYy.png" alt="activate password" /></p>
<h3 id="heading-tldr">TLDR</h3>
<p>Mostly, I wrote the front-end part since the back-end part is quite handy and easy to use, and can be generated!</p>
]]></content:encoded></item><item><title><![CDATA[Upload File to AWS S3 using .NET Web API]]></title><description><![CDATA[Hello!
I want to bring some "guide" how to use AWS SDK .NET, especially using S3. Simple code that you can follow, please navigate to here, in there you will use .NET console.
Preparation

Please install .NET first. You can choose either .NET 5 or .N...]]></description><link>https://hashnode.berviantoleo.my.id/upload-file-to-aws-s3-using-net-web-api</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/upload-file-to-aws-s3-using-net-web-api</guid><category><![CDATA[AWS]]></category><category><![CDATA[.NET]]></category><category><![CDATA[Amazon S3]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Sun, 26 Sep 2021 13:21:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632707000853/yn1hFM8jf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello!</p>
<p>I want to bring some "guide" how to use AWS SDK .NET, especially using S3. Simple code that you can follow, please navigate to <a target="_blank" href="https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/quick-start-s3-1-cross.html">here</a>, in there you will use .NET console.</p>
<h2 id="preparation">Preparation</h2>
<ul>
<li>Please install .NET first. You can choose either .NET 5 or .NET Core 3.1.</li>
</ul>
<p>https://dotnet.microsoft.com/download</p>
<p>(Optional) .NET 6 currently in the RC stage, if you want to try it.</p>
<p>https://dotnet.microsoft.com/download/dotnet/6.0</p>
<ul>
<li>Prepare your project. You can use this command. (if you are already have the project, just skip this step)</li>
</ul>
<p><code>dotnet new webapi -o AWSS3Example</code></p>
<p>Note: In case you can't find the webapi (when use .NET 6), you can use template from .NET 3.1 since in this article using existing project and the existing project using .NET 3.1 and only change the <code>TargetFramework</code> to <code>.net6.0</code>.</p>
<ul>
<li>Add AWS SDK S3 to your project. You can use this command.</li>
</ul>
<p><code>dotnet add AWSS3Example package AWSSDK.S3</code></p>
<p><code>dotnet add AWSS3Example package AWSSDK.Extensions.NETCore.Setup</code></p>
<p>Note: You can change <code>AWSS3Example</code> with your project name.</p>
<ul>
<li>Prepare your AWS Environment and S3</li>
</ul>
<p>I will not bring many steps. You can follow AWS documentation how to setup. As example, you can follow this (the step before setup project): https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/quick-start-s3-1-cross.html</p>
<h2 id="coding-time">Coding Time</h2>
<ul>
<li>I want to write the interface for writing file to S3, so if AWS SDK S3 have major changed, you only change the implementation of the interface. I will write the interface at <code>AWSS3Example/Services/AWS/IAWSS3Service.cs</code>.</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Threading.Tasks;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Http;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">AWSS3Example.Services.AWS</span>
{
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">IAWSS3Service</span>
  {
    <span class="hljs-function">Task&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">UploadFile</span>(<span class="hljs-params">IFormFile formFile</span>)</span>;
  }
}
</code></pre>
<ul>
<li>Write the implementation. Location <code>AWSS3Example/Services/AWS/AWSS3Service.cs</code>.</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Threading.Tasks;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Http;
<span class="hljs-keyword">using</span> Amazon.S3;
<span class="hljs-keyword">using</span> Amazon.S3.Model;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">AWSS3Example.Services.AWS</span>
{
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AWSS3Service</span> : <span class="hljs-title">IAWSS3Service</span>
  {
    <span class="hljs-keyword">private</span> IAmazonS3 _s3Client;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AWSS3Service</span>(<span class="hljs-params">IAmazonS3 amazonS3</span>)</span>
    {
      _s3Client = amazonS3;
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">UploadFile</span>(<span class="hljs-params">IFormFile formFile</span>)</span>
    {
      <span class="hljs-keyword">var</span> location = <span class="hljs-string">$"uploads/<span class="hljs-subst">{formFile.FileName}</span>"</span>;
      <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> stream = formFile.OpenReadStream())
      {
        <span class="hljs-keyword">var</span> putRequest = <span class="hljs-keyword">new</span> PutObjectRequest
        {
          Key = location,
          BucketName = <span class="hljs-string">"upload-test-berv"</span>,
          InputStream = stream,
          AutoCloseStream = <span class="hljs-literal">true</span>,
          ContentType = formFile.ContentType
        };
        <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> _s3Client.PutObjectAsync(putRequest);
        <span class="hljs-keyword">return</span> location;
      }
    }
  }
}
</code></pre>
<ul>
<li>Write the controller. I write at <code>AWSS3Example/Controllers/AWSS3Controller.cs</code>.</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Threading.Tasks;
<span class="hljs-keyword">using</span> AWSS3Example.Services.AWS;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Http;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">AWSS3Example.Controllers</span>
{
  [<span class="hljs-meta">ApiController</span>]
  [<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SThreeController</span> : <span class="hljs-title">ControllerBase</span>
  {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IAWSS3Service _awsS3Service;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SThreeController</span>(<span class="hljs-params">IAWSS3Service awsS3Service</span>)</span>
    {
      _awsS3Service = awsS3Service;
    }

    [<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"upload"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IActionResult&gt; <span class="hljs-title">Upload</span>(<span class="hljs-params">[FromForm] IFormFile file</span>)</span>
    {
      <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> _awsS3Service.UploadFile(uploadFile.File);
      <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span>
      {
        path = result
      });
    }
  }
}
</code></pre>
<ul>
<li>Update the <code>Startup.cs</code></li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Amazon.S3;
<span class="hljs-keyword">using</span> AWSS3Example.Services.AWS;
<span class="hljs-comment">// ... the rest of another using</span>
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Builder;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Hosting;
<span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Configuration;
<span class="hljs-keyword">using</span> Microsoft.Extensions.DependencyInjection;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Hosting;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">AWSS3Example</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Startup</span>(<span class="hljs-params">IConfiguration configuration</span>)</span>
        {
            Configuration = configuration;
        }

        <span class="hljs-keyword">public</span> IConfiguration Configuration { <span class="hljs-keyword">get</span>; }

        <span class="hljs-comment">// This method gets called by the runtime. Use this method to add services to the container.</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ConfigureServices</span>(<span class="hljs-params">IServiceCollection services</span>)</span>
        {
            <span class="hljs-comment">// the rest of another register service ...</span>
            services.AddScoped&lt;IAWSS3Service, AWSS3Service&gt;();
            services.AddAWSService&lt;IAmazonS3&gt;();
            <span class="hljs-comment">// the rest of another register service ...</span>
            services.AddControllers();
        }

        <span class="hljs-comment">// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app, IWebHostEnvironment env</span>)</span>
        {
            <span class="hljs-comment">// the rest of your configure, no need to modify this...</span>
        }
    }
}
</code></pre>
<ul>
<li>Run your project.</li>
</ul>
<p><code>dotnet run --project AWSS3Example</code></p>
<ul>
<li>Test your API</li>
</ul>
<p>Note: In my case, I use different path, so please use the path that you define at Controller.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706994661/YgmaF-dlN.png" alt="Postman Test" /></p>
<ul>
<li>Check your S3</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706996961/TqG91mqSs.png" alt="S3" /></p>
<h2 id="repository">Repository</h2>
<p>You can check here for the repository.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/bervproject/NetCoreAPIBoilerplate">https://github.com/bervproject/NetCoreAPIBoilerplate</a></div>
<h2 id="congrats">Congrats</h2>
<p>Congrats. You are finished build API for upload file to AWS S3. Thank you. Hope you enjoy and if have another suggestion, feel free comment in here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706999116/7U6SY2Efx.jpeg" alt="Unsplash" /></p>
Image source <a href="https://unsplash.com/photos/abkEAOjnY0s">unsplash</a>.]]></content:encoded></item><item><title><![CDATA[File Upload using Elixir, Phoenix, Absinthe and ExAws]]></title><description><![CDATA[Hello, I'm quite new in the elixir world. I want to write some notes so it will help me for later if I want to try this again. This guide will not really details. I will assume that you familiar enough to know about Elixir, Phoenix, Absinthe or ExAws...]]></description><link>https://hashnode.berviantoleo.my.id/file-upload-using-elixir-phoenix-absinthe-and-exaws</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/file-upload-using-elixir-phoenix-absinthe-and-exaws</guid><category><![CDATA[Elixir]]></category><category><![CDATA[Phoenix framework]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Sat, 25 Sep 2021 06:23:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706932527/z7mODJv9h.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, I'm quite new in the elixir world. I want to write some notes so it will help me for later if I want to try this again. This guide will not really details. I will assume that you familiar enough to know about Elixir, Phoenix, Absinthe or ExAws itself. I will assume you are also familiar with AWS especially S3.</p>
<p>Alternative library that you might be interested: https://github.com/stavro/arc</p>
<h2 id="preparation">Preparation</h2>
<ul>
<li>Make sure you are already install Elixir in your computer/PC.</li>
<li>Generate new Phoenix Project. (If you are already have the Phoenix Project, you can skip this step).</li>
</ul>
<p><code>mix archive.install hex phx_new</code></p>
<p><code>mix phx.new elixir_exploration</code></p>
<p>Note:</p>
<ol>
<li><a target="_blank" href="https://hexdocs.pm/phoenix/installation.html#content">Phoenix Installation Documentation</a></li>
<li><a target="_blank" href="https://hexdocs.pm/phoenix/up_and_running.html#content">Phoenix Generate Project</a></li>
<li><p>Make sure you are already have PostgreSQL, if you not want to use database, please refer to note number 2, how to generate without <code>Ecto</code> which handle the database side.</p>
</li>
<li><p>Add Absinthe and ExAWS as Dependencies. Add these to <code>mix.exs</code></p>
</li>
</ol>
<pre><code class="lang-elixir">defp deps do
    [
      ... # rest of dependencies, please not input this too
      {:absinthe, "~&gt; 1.6"},
      {:absinthe_plug, "~&gt; 1.5"},
      {:absinthe_phoenix, "~&gt; 2.0"},
      {:ex_aws, "~&gt; 2.2"},
      {:ex_aws_s3, "~&gt; 2.0"},
      {:poison, "~&gt; 3.0"},
      {:hackney, "~&gt; 1.9"},
      {:sweet_xml, "~&gt; 0.6"},
    ]
  end
</code></pre>
<ul>
<li><p>Download all deps, use <code>mix deps.get</code></p>
</li>
<li><p>Prepare your AWS S3. :) Please read more in their documentation. https://aws.amazon.com/s3/</p>
</li>
<li><p>Prepare your account, we will use <code>AWS_ACCESS_KEY_ID</code> and <code>AWS_SECRET_ACCESS_KEY</code>. Please visit here for more information about <code>ExAWS</code>: https://github.com/ex-aws/ex_aws</p>
</li>
</ul>
<h2 id="lets-code">Let's Code</h2>
<p>My code structure will be like this:</p>
<pre><code><span class="hljs-deletion">- root</span>
<span class="hljs-deletion">-- elixir_exploration</span>
<span class="hljs-deletion">-- elixir_exploration_web</span>
<span class="hljs-comment">--- resolvers # store all GraphQL resolvers</span>
<span class="hljs-comment">--- schema # store all GraphQL schemas</span>
<span class="hljs-deletion">-- schema.ex # store all GraphQL query/mutations</span>
</code></pre><ul>
<li>I will code at GraphQL side first (Absinthe). Please setup the Absinthe first.</li>
</ul>
<p>You can refer this guide: https://hexdocs.pm/absinthe/plug-phoenix.html</p>
<blockquote>
<p>I really love most of popular library, they bring us a nice guide. :)</p>
</blockquote>
<ul>
<li>Write the resolver, I will put in <code>elixir_exploration_web/resolvers/uploads.ex</code></li>
</ul>
<pre><code class="lang-elixir">defmodule ElixirExplorationWeb.Resolvers.Uploads do
  alias ExAws.S3

  def upload_to_aws(_, %{input: input}, _) do
    IO.inspect(input.file)
    request = input.file.path
      |&gt; S3.Upload.stream_file()
      # take care the filename, you should validate this
      |&gt; S3.upload("upload-test-berv", "uploads/#{input.file.filename}")
      |&gt; ExAws.request()
    case request do
      {:ok, _} -&gt; {:ok, "Success"}
      {:error, _} -&gt; {:error, "Please try again"}
    end
  end
end
</code></pre>
<p>Don't forget to update the bucket name. In that example, I use <code>upload-test-berv</code> as the bucket name. I use <code>uploads/#{input.file.filename}</code> as the target file location.</p>
<ul>
<li>Write the schema, I will put in <code>elixir_exploration_web/schema/upload_types.ex</code></li>
</ul>
<pre><code class="lang-elixir">defmodule ElixirExplorationWeb.Schema.UploadTypes do
  use Absinthe.Schema.Notation

  alias ElixirExplorationWeb.Resolvers
  import_types(Absinthe.Plug.Types)

  object :upload_file do
    @desc """
      Upload a file
    """
    field :upload_file, :string do
      arg(:input, non_null(:file_input))
      resolve(&amp;Resolvers.Uploads.upload_to_aws/3)
    end
  end

  input_object :file_input do
    field :file, non_null(:upload)
  end
end
</code></pre>
<ul>
<li>Import those files into <code>elixir_exploration_web/schema.ex</code></li>
</ul>
<pre><code class="lang-elixir">defmodule ElixirExplorationWeb.Schema do
  use Absinthe.Schema

  alias ElixirExplorationWeb.Schema

  import_types(Schema.UploadTypes)

  query do

  end

  mutation do
    import_fields(:upload_file)
  end
end
</code></pre>
<ul>
<li>Update config, I want to setup the default region. Currently I update to <code>config/config.exs</code>, but feel free to add different approach for different env.</li>
</ul>
<pre><code class="lang-elixir">config :ex_aws,
  region: {:system, "AWS_DEFAULT_REGION"}
</code></pre>
<ul>
<li>Write the <code>env.sh</code>, this for setup our environment variable in our system.</li>
</ul>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> AWS_ACCESS_KEY_ID=&lt;your_access_key_id&gt;
<span class="hljs-built_in">export</span> AWS_SECRET_ACCESS_KEY=&lt;your_secret_access_key&gt;
<span class="hljs-built_in">export</span> AWS_DEFAULT_REGION=ap-southeast-1
</code></pre>
<p>Feel free to use another region. :)</p>
<ul>
<li><p>Apply the environment, you can use <code>source env.sh</code>.</p>
</li>
<li><p>Run your Phoenix Server. <code>mix phx.server</code></p>
</li>
<li><p>Test your API. Because my API locate at <code>localhost:4000/api/graphql</code>, so I will use that. If you set another path, please update it from my script below.</p>
</li>
</ul>
<pre><code class="lang-bash">curl -X POST -F query=<span class="hljs-string">"mutation { uploadFile(input: {file: \"my_data\"})}"</span> -F my_data=@mix.exs -H <span class="hljs-string">"Accept:application/json"</span> localhost:4000/api/graphql
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706926311/R0nXrIOAS.png" alt="Elixir Test" /></p>
<ul>
<li>Check your S3</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706928489/-FpmXBEV4.png" alt="S3" /></p>
<h2 id="my-repo">My Repo</h2>
<p>You also can visit my repositories. I will write more in there if I have any updates.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/berviantoleo/elixir-exploration">https://github.com/berviantoleo/elixir-exploration</a></div>
<h2 id="congrats">Congrats</h2>
<p>Yey! Congrats! You've implemented file upload and upload the file to AWS S3. In the next section, maybe I will write to show the result after you upload the file. The approach I will use:</p>
<ol>
<li>Use database as the listing</li>
<li>Call AWS S3 API Directly to get the list</li>
</ol>
<p>I hope I will write in the next month and write each approach in different article.</p>
<p>Thank you. :)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632706930661/LB2KdsIub.jpeg" alt="Thank you image" /></p>
The city at night via <a href="https://unsplash.com/photos/VyC0YSFRDTU">unsplash</a>
]]></content:encoded></item><item><title><![CDATA[Coverage Report for Elixir & Phoenix]]></title><description><![CDATA[Introduction
Hello, I am new at Elixir and Phoenix. I curious about DevOps aspects and Backend aspects. So, that is why I explore more about coverage report and automatic testing. I found great alternative about coverage report, that is ExCoveralls.
...]]></description><link>https://hashnode.berviantoleo.my.id/coverage-report-for-elixir-and-phoenix</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/coverage-report-for-elixir-and-phoenix</guid><category><![CDATA[Elixir]]></category><category><![CDATA[Phoenix framework]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Tue, 31 Aug 2021 14:19:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631603553213/waio-OsR0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Hello, I am new at Elixir and Phoenix. I curious about DevOps aspects and Backend aspects. So, that is why I explore more about coverage report and automatic testing. I found great alternative about coverage report, that is <a target="_blank" href="https://github.com/parroty/excoveralls">ExCoveralls</a>.</p>
<h2 id="setup-excoveralls-to-existing-phoenix-project">Setup ExCoveralls to Existing Phoenix Project</h2>
<p>You can check the settings section of ExCoveralls, <a target="_blank" href="https://github.com/parroty/excoveralls#settings">here</a>. Please refer to their newest settings, this settings might be outdated for later.</p>
<ul>
<li>Add this to <strong>project</strong> at <strong>mix.exs</strong>.</li>
</ul>
<pre><code class="lang-elixir">def project do
  [
    ..., # existing settings
    deps: deps(),
    test_coverage: [tool: ExCoveralls],
    preferred_cli_env: [
      coveralls: :test,
      "coveralls.detail": :test,
      "coveralls.post": :test,
      "coveralls.html": :test
    ]
    # if you want to use espec,
    # test_coverage: [tool: ExCoveralls, test_task: "espec"]
  ]
end
</code></pre>
<ul>
<li>Add this to <strong>deps</strong> at <strong>mix.exs</strong></li>
</ul>
<pre><code class="lang-elixir">defp deps do
  [
    ..., # existing dependencies
    {:excoveralls, "~&gt; 0.10", only: :test},
  ]
end
</code></pre>
<ul>
<li>Create new file with name <strong>coveralls.json</strong> in the root project. This settings to ignore <strong>test</strong> and <strong>deps</strong> folder become coverage area.</li>
</ul>
<pre><code class="lang-json">{
  <span class="hljs-attr">"skip_files"</span>: [
    <span class="hljs-string">"test"</span>,
    <span class="hljs-string">"deps"</span>
  ]
}
</code></pre>
<ul>
<li>To test if it's already installed and works. You can run this command.</li>
</ul>
<pre><code class="lang-bash">MIX_ENV=<span class="hljs-built_in">test</span> mix coveralls
</code></pre>
<h2 id="setup-github-action">Setup Github Action</h2>
<p>I use Github Action as my main CI/CD platform. Currently I use this configuration.</p>
<pre><code class="lang-yml"><span class="hljs-attr">name:</span> <span class="hljs-string">Elixir</span> <span class="hljs-string">CI</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">main</span> ]
  <span class="hljs-attr">pull_request:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">main</span> ]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">and</span> <span class="hljs-string">test</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-20.04</span>
    <span class="hljs-attr">services:</span>
      <span class="hljs-comment"># Label used to access the service container</span>
      <span class="hljs-attr">postgres:</span>
        <span class="hljs-comment"># Docker Hub image</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">postgres:13-alpine</span>
        <span class="hljs-comment"># Provide the password for postgres</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">postgres</span>
        <span class="hljs-comment"># Set health checks to wait until postgres has started</span>
        <span class="hljs-attr">options:</span> <span class="hljs-string">&gt;-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
</span>        <span class="hljs-attr">ports:</span>
          <span class="hljs-comment"># Maps tcp port 5432 on service container to the host</span>
          <span class="hljs-bullet">-</span> <span class="hljs-number">5432</span><span class="hljs-string">:5432</span>
    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">erlef/setup-beam@v1</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">otp-version:</span> <span class="hljs-string">'22.2'</span>
        <span class="hljs-attr">elixir-version:</span> <span class="hljs-string">'1.10'</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Restore</span> <span class="hljs-string">dependencies</span> <span class="hljs-string">cache</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/cache@v2</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">deps</span>
        <span class="hljs-attr">key:</span> <span class="hljs-string">${{</span> <span class="hljs-string">runner.os</span> <span class="hljs-string">}}-mix-${{</span> <span class="hljs-string">hashFiles('**/mix.lock')</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">restore-keys:</span> <span class="hljs-string">${{</span> <span class="hljs-string">runner.os</span> <span class="hljs-string">}}-mix-</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">dependencies</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">mix</span> <span class="hljs-string">deps.get</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Check</span> <span class="hljs-string">Format</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">mix</span> <span class="hljs-string">format</span> <span class="hljs-string">--check-formatted</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">tests</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">mix</span> <span class="hljs-string">coveralls.json</span>
      <span class="hljs-attr">env:</span>
        <span class="hljs-attr">MIX_ENV:</span> <span class="hljs-string">test</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">to</span> <span class="hljs-string">Codecov</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">|
        curl -Os https://uploader.codecov.io/latest/linux/codecov
        chmod +x codecov
        ./codecov</span>
</code></pre>
<p>This configuration will automatically to add coverage results to <a target="_blank" href="https://codecov.io">Codecov</a>. The result will be like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631603548908/6uEx8QA8Z.png" alt="Codecov Result" /></p>
<p><strong>Note</strong>: The configuration will work for public repository. If you use private repository, please consider modify the configuration. You need to change the line of <code>./codecov</code> become <code>./codecov -t ${CODECOV_TOKEN}</code>.</p>
<p>Here is my example app.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/berviantoleo/elixir-exploration">https://github.com/berviantoleo/elixir-exploration</a></div>
<h2 id="thank-you">Thank you</h2>
<p>Thank you for read this article. If have any comments to improve this article, feel free to comment here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631603551600/IDpSHfKgw.jpeg" alt="Thank you" /></p>
Image from <a href="https://unsplash.com/photos/0YbeoQOX89k">Unsplash</a>]]></content:encoded></item><item><title><![CDATA[Fake REST for Helping you to Test]]></title><description><![CDATA[Sometimes, not sometimes, but usually, we need to have parallel task between Front-end development and Back-end development. Oh no, the Front-end team need to know the Request/Response object that expected to know. Yeah, that context will usual meet ...]]></description><link>https://hashnode.berviantoleo.my.id/fake-rest-for-helping-you-to-test</link><guid isPermaLink="true">https://hashnode.berviantoleo.my.id/fake-rest-for-helping-you-to-test</guid><dc:creator><![CDATA[Bervianto Leo Pratama]]></dc:creator><pubDate>Sun, 08 Aug 2021 17:29:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/3rFq-RHSNLg/upload/33dcb859900bcfbf729f94991141b263.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sometimes, not sometimes, but usually, we need to have parallel task between Front-end development and Back-end development. Oh no, the Front-end team need to know the Request/Response object that expected to know. Yeah, that context will usual meet in the project. It will best if we have the actual services, but sometimes it’s impossible to have or implement that in short time. So, we need to another alternatives to help Front-end team, so they don’t need to wait.</p>
<h3 id="heading-mock-api">Mock API</h3>
<p>We usually ended the solution with Mock API. At least the Front-end team know what is the request object and the response object. Is it will bring <em>json</em>, <em>xml,</em> or <em>files</em>? That’s why we need Mock API. But, yeah, we need the Mock API that <strong>no need take long time to build</strong> and <strong>no need much code to write</strong>. We can say that, we need <strong>effortless solution</strong>. If we still write many codes (I mean, too much effort) just for Mock API, I want to say that, it is useless and better we create the solution directly.</p>
<h4 id="heading-simple-rest-api-mock">Simple REST API (Mock)</h4>
<p>I found a solution that I think it’s good for simple REST API and just need the CRUD (Create, Read, Update and Delete). You can check <a target="_blank" href="https://my-json-server.typicode.com/">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631626013704/NjVPP_4Cd.png" alt /></p><figcaption>My JSON Server</figcaption><p></p>
<p>I am not really sure if that service will reliable, but at least you can use it for short time, and the important things is effortless. But, please take care, since this is public services, make sure you <strong>not store any confidential data</strong>. You can check the guidance. If you need locally or private solution, you can use <a target="_blank" href="https://github.com/typicode/json-server">Json Server</a>. It is easy to setup. Since the SaaS (Software as a Service), the <strong>My JSON Server</strong> is public services, I recommend you to setup the <strong>Json Server</strong> if you really need to be private and have some confidential data (but still not recommend to store this kind of data, better just reasonable dummy data). The disadvantage of this kind Mock API, it’s only support json (when I write this article) for request and response, but good enough if we need the simple REST API.</p>
<h4 id="heading-postman-api">Postman API</h4>
<p>I think this is quite good solution or alternative to create mock API. Please refer this <a target="_blank" href="https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/setting-up-mock/">documentation</a> for how to create the Mock API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631626015343/Ipl7YqSfc.png" alt /></p><figcaption>Create New API</figcaption><p></p>
<p>I think this is really good solution if you need complex request/response of the API. You can define the collections for request/response, give the description. You can create the documentation also! I want to recommend you to use this features. Somehow, yeah, you can do many things in here.</p>
<h3 id="heading-happy-exploring">Happy Exploring!</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631626017147/iLAcnxJH2.jpeg" alt /></p><figcaption>Photo by <a href="https://unsplash.com/@acharki95?utm_source=medium&amp;utm_medium=referral">Aziz Acharki</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption><p></p>
<p>I just want to say Happy Exploring! I only want to recommend some tools/services that will help you to create the Mock API. So at least you can bring some “contract” to Front-end teams. If you have another solutions or alternatives, feel free to add and comment here.</p>
<p>I just want to say Happy Exploring! I only want to recommend some tools/services that will help you to create the Mock API. So at least you can bring some “contract” to Front-end teams. If you have another solutions or alternatives, feel free to add and comment here.</p>
]]></content:encoded></item></channel></rss>