<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ope Adeyomoye</title>
    <description>The latest articles on DEV Community by Ope Adeyomoye (@ope).</description>
    <link>https://dev.to/ope</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F19060%2F532ba71e-16a0-4916-862c-3e268b957859.jpg</url>
      <title>DEV Community: Ope Adeyomoye</title>
      <link>https://dev.to/ope</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ope"/>
    <language>en</language>
    <item>
      <title>filterd: AI-based Image Moderation for Everyday Websites</title>
      <dc:creator>Ope Adeyomoye</dc:creator>
      <pubDate>Fri, 14 Jan 2022 07:50:47 +0000</pubDate>
      <link>https://dev.to/ope/filterd-ai-based-image-moderation-for-everyday-websites-2nej</link>
      <guid>https://dev.to/ope/filterd-ai-based-image-moderation-for-everyday-websites-2nej</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;filterd is a concept of a company that offers an API to help detect and tag potentially offensive content in images, using AI.&lt;/p&gt;

&lt;p&gt;A sample use case would be to automate content moderation on blogs / forums / others websites where end-users are allowed to put up images.&lt;/p&gt;

&lt;p&gt;The submission includes customer sign-up, authentication, API key issuance, and an API endpoint for annotating customers' images.&lt;/p&gt;

&lt;p&gt;On annotating an image with the API, the customer gets a "suggestion" to express accept or decline posting the image on their website. If the analysis is inconclusive, they're nudged to manually review the image.&lt;/p&gt;

&lt;p&gt;All data is stored in MongoDB Atlas.&lt;/p&gt;

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

&lt;p&gt;Choose Your Own Adventure&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opeadeyomoye"&gt;
        opeadeyomoye
      &lt;/a&gt; / &lt;a href="https://github.com/opeadeyomoye/filterd"&gt;
        filterd
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
filterd&lt;/h1&gt;
&lt;p&gt;AI-based content moderation.&lt;/p&gt;
&lt;p&gt;See &lt;a href="https://filterd.cloud" rel="nofollow"&gt;https://filterd.cloud&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opeadeyomoye/filterd"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


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

&lt;p&gt;The project uses &lt;a href="https://cloud.google.com/vision"&gt;Cloud Vision&lt;/a&gt;, MongoDB Atlas and a PHP backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

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

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

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

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

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

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

</description>
      <category>atlashackathon</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Volafile</title>
      <dc:creator>Ope Adeyomoye</dc:creator>
      <pubDate>Mon, 11 Jan 2021 06:42:36 +0000</pubDate>
      <link>https://dev.to/ope/volafile-3l7c</link>
      <guid>https://dev.to/ope/volafile-3l7c</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;A simple, ephemeral file-sharing service.&lt;/p&gt;

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

&lt;p&gt;Built for Business&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://volafile-76j4i.ondigitalocean.app"&gt;https://volafile-76j4i.ondigitalocean.app&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1qRJEps6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zm66cxworbk6uy04bc4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1qRJEps6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zm66cxworbk6uy04bc4j.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0iH7zrND--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1mf1i5s49kauqteberj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0iH7zrND--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1mf1i5s49kauqteberj0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--umQM4R0U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/94bdoj2xhapue7d2kuzy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--umQM4R0U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/94bdoj2xhapue7d2kuzy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TLU2IUia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oiuwl8ftlrxjgncl4u00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TLU2IUia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oiuwl8ftlrxjgncl4u00.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NG6yKFQ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ipgfc2b4p9p4u8a66hxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NG6yKFQ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ipgfc2b4p9p4u8a66hxl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;Volafile helps you share files privately. You can upload a file and get a unique download link that's known only to you and other people you might share it with.&lt;/p&gt;

&lt;p&gt;You can optionally add another layer of secrecy with a password. That way, if you accidentally share your download link in the wrong places, your private files don't suddenly become publicly available. Any one with the link will need that password before they can access your file(s). &lt;/p&gt;

&lt;p&gt;At the moment, each upload automatically expires after 24 hours, so any attempts to download your file(s) after that time will fail and your files are permanently deleted.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/opeadeyomoye/volafile"&gt;https://github.com/opeadeyomoye/volafile&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;MIT&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Firefox_Send"&gt;Firefox Send&lt;/a&gt; was a lovely service before it was taken down. It was great to have a way to securely make anonymous, short-lived file shares. Volafile is inspired by the late Firefox Send.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it
&lt;/h3&gt;

&lt;p&gt;Volafile currently runs as a traditional web app in 1+ Docker containers on DigitalOcean's &lt;a href="https://www.digitalocean.com/products/app-platform/"&gt;App Platform&lt;/a&gt;. It also uses a MySQL database based on DigitalOcean's managed database service and stores uploaded files with &lt;a href="https://www.digitalocean.com/products/spaces/"&gt;Spaces&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dohackathon</category>
    </item>
    <item>
      <title>Securing your Azure Web App with Let's Encrypt.</title>
      <dc:creator>Ope Adeyomoye</dc:creator>
      <pubDate>Mon, 20 Apr 2020 03:12:27 +0000</pubDate>
      <link>https://dev.to/ope/securing-your-azure-web-app-with-let-s-encrypt-4g99</link>
      <guid>https://dev.to/ope/securing-your-azure-web-app-with-let-s-encrypt-4g99</guid>
      <description>&lt;p&gt;&lt;em&gt;This post assumes that you have deployed your web app in a Docker container on &lt;a href="https://azure.microsoft.com/en-us/services/app-service/" rel="noopener noreferrer"&gt;Microsoft Azure's fully-managed App Service&lt;/a&gt; platform. It also assumes that, for some reason, you want to manually obtain an SSL certificate for your app, and manually renew it before it expires.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we get to certificates...
&lt;/h2&gt;

&lt;p&gt;When you deploy your app on Azure's App Service platform, you automatically get a URL that can be used to view your app. It'll usually be in the form: &lt;a href="https://your-app-name.azurewebsites.net" rel="noopener noreferrer"&gt;https://your-app-name.azurewebsites.net&lt;/a&gt;. If you like the free domain and don't exactly see a need to use a custom domain, then you probably don't need most of the rest of this post. I'd suggest you turn on "HTTPS only" tho.&lt;/p&gt;

&lt;p&gt;Chances are, however, you &lt;em&gt;do&lt;/em&gt; want to serve your app using a custom domain. If you've not added a custom domain to your App Service app, please see &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-custom-domain#map-your-domain" rel="noopener noreferrer"&gt;Azure's docs&lt;/a&gt; on this and follow the steps there.&lt;/p&gt;

&lt;h2&gt;
  
  
  It could be much easier
&lt;/h2&gt;

&lt;p&gt;Azure lets you create a free certificate and add it your App Service app at the click of a couple buttons. It's issued by &lt;a href="https://www.digicert.com/" rel="noopener noreferrer"&gt;DigiCert&lt;/a&gt;, managed by App Service, and renewed automatically.&lt;/p&gt;

&lt;p&gt;If you'd like to use this instead of rolling your own, see &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-certificate#create-a-free-certificate-preview" rel="noopener noreferrer"&gt;Azure's docs on it&lt;/a&gt; and don't forget to turn on HTTPS Only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a certificate
&lt;/h2&gt;

&lt;p&gt;Let's Encrypt recommends using the &lt;a href="https://certbot.eff.org" rel="noopener noreferrer"&gt;Certbot&lt;/a&gt; ACME client for certificate issuance. Certbot can automate certificate issuance and installation, but this post demonstrates using Certbot in manual mode.&lt;/p&gt;

&lt;p&gt;First, let's install Certbot. On Debian 10+ systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;certbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For other Debian versions, linux distros or different operating systems, please see &lt;a href="https://certbot.eff.org/docs/install.html#operating-system-packages" rel="noopener noreferrer"&gt;Certbot's installation docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issuing a certificate
&lt;/h3&gt;

&lt;p&gt;Now, let's get an SSL certificate issued for &lt;code&gt;yourdomain.com&lt;/code&gt;. On the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot certonly &lt;span class="nt"&gt;-d&lt;/span&gt; yourdomain.com &lt;span class="nt"&gt;--manual&lt;/span&gt; &lt;span class="nt"&gt;--preferred-challenges&lt;/span&gt; dns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;via the &lt;code&gt;certonly&lt;/code&gt; sub-command, tells Certbot to simply obtain a new
certificate, and not install it on your local machine;&lt;/li&gt;
&lt;li&gt;tells Certbot to use a DNS challenge. As opposed to an HTTPS challenge
where you'd have to upload a certain file to a specific directory on
your server, a DNS challenge requires you to add a DNS TXT record on your domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a few simple questions, Certbot will ask you to create a DNS TXT record, usually under the name &lt;code&gt;_acme-challenge.yourdomain.com&lt;/code&gt;, with a value it provides. Usually, you'll do this via your DNS provider. Please see your DNS provider's docs on how to create DNS records for your domain.&lt;/p&gt;

&lt;p&gt;If it all went well, you should see a message like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/yourdomain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/yourdomain.com/privkey.pem
   Your cert will expire on &amp;lt;some-date&amp;gt;. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add your shiny new certificate to App Service
&lt;/h2&gt;

&lt;p&gt;To secure a custom domain for your web app, Azure requires a private certificate in the &lt;a href="https://en.wikipedia.org/wiki/PKCS_12" rel="noopener noreferrer"&gt;PKCS #12&lt;/a&gt; file format. Certbot does not generate this file by default, but you can create it using some of the files it &lt;em&gt;does&lt;/em&gt; generate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a private certificate
&lt;/h3&gt;

&lt;p&gt;For this, you'll need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;your server certificate file;&lt;/li&gt;
&lt;li&gt;the private key for your certificate;&lt;/li&gt;
&lt;li&gt;the intermediate certificate from Let's Encrypt CA.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All those files can be found at &lt;code&gt;/etc/letsencrypt/live/yourdomain.com/&lt;/code&gt;, and you can simply run the following commands to create your private certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a staging area&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /tmp/sandbox &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp/sandbox

&lt;span class="c"&gt;# copy the needed files over&lt;/span&gt;
&lt;span class="nv"&gt;$ SOURCE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/letsencrypt/live/yourdomain.com
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nv"&gt;$SOURCE&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;cert.pem,privkey.pem,chain.pem&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# make the files your own&lt;/span&gt;
&lt;span class="c"&gt;# assuming your username is ope...&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo chown &lt;/span&gt;ope &lt;span class="k"&gt;*&lt;/span&gt;.pem

&lt;span class="c"&gt;# finally, create the private certificate,&lt;/span&gt;
&lt;span class="c"&gt;# saving it to "certificate.pfx"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;openssl pkcs12 &lt;span class="nt"&gt;-export&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; certificate.pfx &lt;span class="nt"&gt;-inkey&lt;/span&gt; privkey.pem &lt;span class="nt"&gt;-in&lt;/span&gt; cert.pem &lt;span class="nt"&gt;-certfile&lt;/span&gt; chain.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last command asks you to enter an export password. Please make note of that password since you'll need it when uploading your private certificate on Azure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload the private certificate
&lt;/h3&gt;

&lt;p&gt;From your &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;Azure portal&lt;/a&gt;, navigate to your App Service web app and click on the "Custom domains" menu item. In the page that comes up, find the row that contains the custom domain you added and click "Add binding" under the "SSL Binding" column.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs9qo3bwx5jed7cn8f84c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs9qo3bwx5jed7cn8f84c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the sidebar that comes up, click "Upload PFX Certificate"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftrk7uu47akhymlbiqcgz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftrk7uu47akhymlbiqcgz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the form that's displayed next, select the &lt;code&gt;certificate.pfx&lt;/code&gt; file you created, and enter the password you chose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2vv7a1nhve9p5c6nr5gd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2vv7a1nhve9p5c6nr5gd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Upload" to proceed. The next screen should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fitad7sfi9cknia1sz4yn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fitad7sfi9cknia1sz4yn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Add Binding" once you've selected the relevant options.&lt;/p&gt;

&lt;p&gt;That's it! Once the deployment is complete on Azure, you can now navigate to your web app, via your custom domain, using HTTPS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean up
&lt;/h3&gt;

&lt;p&gt;You can't subsequently download your private certificate from Azure App Service, so you might want to store the local copy somewhere other than the system temp directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /tmp/sandbox/certificate.pfx /path/to/dir/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once your private certificate is safe, you may clear out the sandbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; /tmp/sandbox/ &lt;span class="nt"&gt;-R&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consider turning on "HTTPS Only"
&lt;/h3&gt;

&lt;p&gt;Azure App Service has a little handy feature, called &lt;em&gt;HTTPS Only&lt;/em&gt;, that helps redirect all of your app's HTTP traffic to HTTPS.&lt;/p&gt;

&lt;p&gt;That makes sure that any client communication with your app is encrypted, and visitors aren't scared away with "Connection not secure" messages from their browsers.&lt;/p&gt;

&lt;p&gt;To turn this on, head on to your App Service within the &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;Azure portal&lt;/a&gt;, and click on the &lt;em&gt;TLS/SSL settings&lt;/em&gt; menu item. You'll find the option there under "Protocol Settings".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd1r03j49n3s69bg3gtog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd1r03j49n3s69bg3gtog.png"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>letsencrypt</category>
    </item>
    <item>
      <title>Do you (re)arrange your class methods? Why?</title>
      <dc:creator>Ope Adeyomoye</dc:creator>
      <pubDate>Thu, 21 Sep 2017 16:31:20 +0000</pubDate>
      <link>https://dev.to/ope/do-you-rearrange-your-class-methods-why</link>
      <guid>https://dev.to/ope/do-you-rearrange-your-class-methods-why</guid>
      <description>&lt;p&gt;Lots of (open-source) libraries I go through seem to (re)arrange the methods of member classes in a specific manner e.g. such that any class methods that are to be used by other methods within that class are defined first.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dispatcher&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isDispatchable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isDispatchable&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// implementation goes here...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;isDispatchable()&lt;/code&gt; is defined before the method that uses it.&lt;/p&gt;

&lt;p&gt;I generally just append new methods to the end of the class whether or not the other methods that use it are above or below. Should I be sent north of the wall?&lt;/p&gt;

&lt;p&gt;What do you do?&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>What are the caveats of using global functions and/or classes with all-static methods?</title>
      <dc:creator>Ope Adeyomoye</dc:creator>
      <pubDate>Mon, 19 Jun 2017 23:31:46 +0000</pubDate>
      <link>https://dev.to/ope/what-are-the-caveats-with-using-global-functions-andor-classes-with-all-static-methods</link>
      <guid>https://dev.to/ope/what-are-the-caveats-with-using-global-functions-andor-classes-with-all-static-methods</guid>
      <description>&lt;p&gt;Within the last one year of my three-year journey into web development (on the LAMP stack), I've seen a lot of articles, blog posts etc., where programmers all but liken using global functions and static methods to deploying a nuclear warhead aimed at the server(s) where your application is hosted, but (most of them) without really explaining why that may be the case.&lt;/p&gt;

&lt;p&gt;I don't have a CS background (yet), and I just saw another such post some 20 minutes ago so I was wondering whether we could shed some light on this topic here on dev.&lt;/p&gt;

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