<?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>Forem: Mrinmoy Das</title>
    <description>The latest articles on Forem by Mrinmoy Das (@goromlagche).</description>
    <link>https://forem.com/goromlagche</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%2F750340%2F95eaea87-1c22-47f7-81d1-ed9e5158b699.png</url>
      <title>Forem: Mrinmoy Das</title>
      <link>https://forem.com/goromlagche</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/goromlagche"/>
    <language>en</language>
    <item>
      <title>Parallelism and custom variables in CircleCI</title>
      <dc:creator>Mrinmoy Das</dc:creator>
      <pubDate>Wed, 02 Mar 2022 20:14:47 +0000</pubDate>
      <link>https://forem.com/goromlagche/parallelism-and-custom-variables-in-circleci-jhl</link>
      <guid>https://forem.com/goromlagche/parallelism-and-custom-variables-in-circleci-jhl</guid>
      <description>&lt;p&gt;CircleCI allows us to specify a job’s parallelism level. In this post, we will try to further customize that using a custom CircleCI parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Premise
&lt;/h2&gt;

&lt;p&gt;We can use CircleCI’s &lt;a href="https://circleci.com/docs/2.0/parallelism-faster-jobs/"&gt;parallelism&lt;/a&gt; feature to split a job in parallel by spreading them across multiple separate executors.&lt;/p&gt;

&lt;p&gt;But sometimes we want to customize the parallelism count based on various other parameters.&lt;/p&gt;

&lt;p&gt;One example of this would be, let’s say we have two kinds of workflows. A &lt;code&gt;ci-workflow&lt;/code&gt; that runs every time. And a &lt;code&gt;nightly&lt;/code&gt; workflow that runs at a certain time every night and builds the nightly release.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  rspec:
    executor: rspec-executor
    parallelism: 30
    steps: ...

workflows:
  nightly:
    triggers:
      - schedule:
          cron: "00 10 * * *"
          filters:
            branches:
              only:
                - master

    jobs:
      - rspec:
          requires:
            - bundle-install

  ci-workflow:
    jobs:
      - rspec:
          requires:
            - bundle-install

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

&lt;/div&gt;



&lt;p&gt;We are using parallelism of 30 for our RSpec tests. For both the workflows. Now &lt;code&gt;nightly&lt;/code&gt; runs happen at a low traffic time when most of the devs are asleep. We can reduce the number of parallelism for just the nightly workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;CircleCI does not provide an out-of-the-box solution for the above problem. We will need to rely on a custom parameter to solve this problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  rspec:
    executor: rspec-executor
    parameters:
      machines:
        type: integer
        default: 30
    parallelism: &amp;lt;&amp;lt; parameters.machines &amp;gt;&amp;gt;
    steps: ...

workflows:
  nightly:
    triggers:
      - schedule:
          cron: "00 10 * * *"
          filters:
            branches:
              only:
                - master

    jobs:
      - rspec:
          requires:
            - bundle-install

  ci-workflow:
    jobs:
      - rspec:
        machines: 10
          requires:
            - bundle-install

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

&lt;/div&gt;



&lt;p&gt;Using a pipeline parameter like above we can customize the parallelism value in CircleCI.&lt;/p&gt;

&lt;p&gt;Until next time! ❤️&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>rspec</category>
    </item>
    <item>
      <title>Sql injection and prepared statements</title>
      <dc:creator>Mrinmoy Das</dc:creator>
      <pubDate>Sat, 06 Nov 2021 21:30:47 +0000</pubDate>
      <link>https://forem.com/goromlagche/sql-injection-and-prepared-statements-el8</link>
      <guid>https://forem.com/goromlagche/sql-injection-and-prepared-statements-el8</guid>
      <description>&lt;p&gt;We will explore how to be safe against sql 💉 attacks. Using bound parameters and prepared statements.&lt;/p&gt;

&lt;p&gt;Most of the time when interacting with the database from rails applications, we use &lt;code&gt;ActiveRecord&lt;/code&gt; and most of the time we can just use the ORM to generate the sql query.&lt;/p&gt;

&lt;p&gt;But sometimes we might need to venture out of the usual path and write our own queries. Sometimes we need to write complex reporting queries.&lt;/p&gt;

&lt;p&gt;For example, let us say we need to find the distance between two coordinates or words. In these cases, there is no ready-made help available from &lt;code&gt;active-record&lt;/code&gt;. We will need to write custom sql queries.&lt;/p&gt;

&lt;p&gt;Let us move on to a concrete example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seed Database
&lt;/h2&gt;

&lt;p&gt;To setup our test environment, we will insert an entire dictionary to the database as seed data.&lt;/p&gt;

&lt;p&gt;We will start with setting up a Postgres instance and also check the IP address which will be helpful later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5CfyLtNC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/start_pg_2021-11-07-02:17:03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5CfyLtNC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/start_pg_2021-11-07-02:17:03.png" alt="start_pg" width="572" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can fire the psql shell and create &lt;code&gt;words&lt;/code&gt; tables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FEbpXGAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/create_table_2021-11-07-02:19:04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FEbpXGAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/create_table_2021-11-07-02:19:04.png" alt="create_table" width="628" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will start a ruby container and install a dictionary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3I0k4SGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/install_dict_2021-11-07-02:11:28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3I0k4SGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/install_dict_2021-11-07-02:11:28.png" alt="install_dict" width="659" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to write some code to seed the database with the dictionary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dmTHIrDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/seed_data_2021-11-07-02:25:58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dmTHIrDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/seed_data_2021-11-07-02:25:58.png" alt="seed_data" width="880" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have successfully seed the database with &lt;code&gt;102774&lt;/code&gt; records.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL 💉
&lt;/h2&gt;

&lt;p&gt;Now that we have the database setup, let us define the task at hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We would like to grab the 5 closest matches for an user input word.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can use trigram search for this. And Postgres has &lt;a href="https://www.postgresql.org/docs/current/pgtrgm.html"&gt;pg_trgm&lt;/a&gt; module which provides us with the necessary tools. The &lt;code&gt;&amp;lt;-&amp;gt;&lt;/code&gt; operator Returns the ‘distance’ between the arguments.&lt;/p&gt;

&lt;p&gt;And to run the query we can use &lt;code&gt;ActiveRecord::Base.connection.execute&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wffzlwz0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/raw_sql_1_2021-11-07-02:51:36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wffzlwz0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/raw_sql_1_2021-11-07-02:51:36.png" alt="raw_sql_1" width="880" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But that is prone to sql injection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TNpkZq_v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/raw_sql_2_2021-11-07-02:52:01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TNpkZq_v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/raw_sql_2_2021-11-07-02:52:01.png" alt="raw_sql_2" width="880" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are roughly two well-known safe-guards present to solve this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Quoting&lt;/li&gt;
&lt;li&gt;Bind Parameters&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Quoting
&lt;/h3&gt;

&lt;p&gt;We can quote the column value to help prevent sql injection.&lt;/p&gt;

&lt;p&gt;ActiveRecord provides us with &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Quoting.html#method-i-quote"&gt;ActiveRecord::Base.connection.quote&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fGTzSN0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/quoting_2021-11-07-02:58:40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fGTzSN0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/quoting_2021-11-07-02:58:40.png" alt="quoting" width="880" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Important to remember&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Connection quoting in Rails uses a db connection from the existing pool, a repeated call and a heavy load might affect performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Bind Parameters And Prepared Statements
&lt;/h3&gt;

&lt;p&gt;In most DBMS we can use a prepared statement, which pre-compiles the SQL query, separating it from data.&lt;/p&gt;

&lt;p&gt;It is a server-side object that can be used to optimize performance, reducing/eliminating SQL injection attacks.&lt;/p&gt;

&lt;p&gt;Postgresql support PREPARED statement, you can read more about it &lt;a href="https://www.postgresql.org/docs/9.3/sql-prepare.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let us fire up the psql shell and use PREPARED statements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3uyIFNlE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/bind_query_2021-11-07-03:25:20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3uyIFNlE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/bind_query_2021-11-07-03:25:20.png" alt="bind_query" width="880" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can check the pg log to see how it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C94js94P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/pg_log_1_2021-11-07-03:22:08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C94js94P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/pg_log_1_2021-11-07-03:22:08.png" alt="pg_log_1" width="880" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back to rails. How do we achieve this using ActiveRecord?&lt;/p&gt;

&lt;p&gt;Well ActiveRecord has &lt;a href="https://api.rubyonrails.org/v6.1.4/classes/ActiveRecord/Querying.html#method-i-find_by_sql"&gt;find_by_sql&lt;/a&gt; method, which helps us with this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JlP5slmf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/find_by_sql_2021-11-07-03:11:15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JlP5slmf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/find_by_sql_2021-11-07-03:11:15.png" alt="find_by_sql" width="880" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us check the pg log. To verify if it is working as intended.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k5CEXwnv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/pg_log_2_2021-11-07-03:33:47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k5CEXwnv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/pg_log_2_2021-11-07-03:33:47.png" alt="pg_log_2" width="880" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Important to note, prepared statement’s lifecycle is per-connection basis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prepared statements only last for the duration of the current database session. When the session ends, the prepared statement is forgotten.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can verify this by disconnecting and checking the log.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iJGSgl5Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/pg_log_3_2021-11-07-03:38:51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iJGSgl5Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.mrinmoydas.com/assets/images/pg_log_3_2021-11-07-03:38:51.png" alt="pg_log_3" width="880" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, that is all I had to share on sql injections.&lt;/p&gt;

&lt;p&gt;Until next week! ❤️&lt;/p&gt;

</description>
      <category>sql</category>
      <category>postgres</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
