<?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: shriramcs</title>
    <description>The latest articles on DEV Community by shriramcs (@shriramcs).</description>
    <link>https://dev.to/shriramcs</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F267704%2F9f97bf05-8045-4ff0-8153-385bd068ac00.jpg</url>
      <title>DEV Community: shriramcs</title>
      <link>https://dev.to/shriramcs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shriramcs"/>
    <language>en</language>
    <item>
      <title>How I Stopped Hardcoding Permissions in My Frontend</title>
      <dc:creator>shriramcs</dc:creator>
      <pubDate>Wed, 22 Jul 2026 12:17:23 +0000</pubDate>
      <link>https://dev.to/shriramcs/stop-scattering-if-role-admin-everywhere-a-3-level-permission-tree-for-page-section-4bfk</link>
      <guid>https://dev.to/shriramcs/stop-scattering-if-role-admin-everywhere-a-3-level-permission-tree-for-page-section-4bfk</guid>
      <description>&lt;p&gt;Most apps start their access control with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;canEditReportsSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;)&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EDITOR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADMIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&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;It works, right up until you have a dozen pages, each with a few sections, each&lt;br&gt;
needing independent read/write rules per role. Now you've got dozens of these&lt;br&gt;
little arrays scattered across the codebase, and adding a new role means hunting&lt;br&gt;
down every single one and hoping you didn't miss any.&lt;br&gt;
0&lt;br&gt;
There's a much simpler model that scales cleanly: a &lt;strong&gt;three-level permission&lt;br&gt;
tree&lt;/strong&gt; — &lt;code&gt;page → section → { r, w }&lt;/code&gt; - plus one generic function that walks it.&lt;br&gt;
No new library, no framework lock-in, just a data structure and ~5 lines of code.&lt;/p&gt;
&lt;h2&gt;
  
  
  The shape of the data
&lt;/h2&gt;

&lt;p&gt;Instead of scattering role checks in code, define &lt;strong&gt;one permission tree per&lt;br&gt;
role&lt;/strong&gt;. Three levels deep:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Page&lt;/strong&gt; — the top-level feature/route (&lt;code&gt;dashboard&lt;/code&gt;, &lt;code&gt;reports&lt;/code&gt;, &lt;code&gt;settings&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section&lt;/strong&gt; — a sub-area within that page (&lt;code&gt;overview&lt;/code&gt;, &lt;code&gt;summary&lt;/code&gt;, &lt;code&gt;billing&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action&lt;/strong&gt; — &lt;code&gt;r&lt;/code&gt; (read) or &lt;code&gt;w&lt;/code&gt; (write)
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dashboard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"overview"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"analytics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"export"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"general"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"billing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This one blob fully describes what a single role can see and do. Give each role&lt;br&gt;
its own tree, e.g. for three common roles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page&lt;/th&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;Viewer&lt;/th&gt;
&lt;th&gt;Editor&lt;/th&gt;
&lt;th&gt;Admin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dashboard&lt;/td&gt;
&lt;td&gt;overview&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dashboard&lt;/td&gt;
&lt;td&gt;analytics&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reports&lt;/td&gt;
&lt;td&gt;summary&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reports&lt;/td&gt;
&lt;td&gt;export&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;settings&lt;/td&gt;
&lt;td&gt;general&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;settings&lt;/td&gt;
&lt;td&gt;billing&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;r, w&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice how this reads almost like a spreadsheet a product owner could fill in —&lt;br&gt;
that's the point. It's declarative data, not scattered &lt;code&gt;if&lt;/code&gt; statements, so&lt;br&gt;
non-engineers can review it and engineers don't have to guess what a role does.&lt;/p&gt;
&lt;h2&gt;
  
  
  The generic access-check function
&lt;/h2&gt;

&lt;p&gt;Once permissions are just nested objects, checking access is one small,&lt;br&gt;
reusable, framework-agnostic function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissionTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;permissionTree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;permissionTree&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;page&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;pageNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sectionNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pageNode&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;section&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;sectionNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sectionNode&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&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="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;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;checkAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// false for Viewer/Editor... true for Admin&lt;/span&gt;
&lt;span class="nf"&gt;checkAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;overview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;r&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// true for all three roles above&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works identically whether &lt;code&gt;permissionTree&lt;/code&gt; comes from Vuex/Redux/Zustand&lt;br&gt;
state, a React context, or is just passed around as a plain object — it has zero&lt;br&gt;
framework dependencies. It's also &lt;strong&gt;fail-closed by design&lt;/strong&gt;: any missing page,&lt;br&gt;
missing section, or typo in the path returns &lt;code&gt;false&lt;/code&gt; rather than throwing or&lt;br&gt;
accidentally granting access.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wiring it into your UI
&lt;/h2&gt;

&lt;p&gt;Wrap the raw function in named, intention-revealing helpers rather than calling&lt;br&gt;
&lt;code&gt;checkAccess([...])&lt;/code&gt; inline everywhere — this keeps each resource path in exactly&lt;br&gt;
one place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canViewReportsExport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;checkAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;r&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canEditReportsExport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;checkAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use them wherever you'd normally reach for a role check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Navigation&lt;/strong&gt; — hide a page link entirely if no section within it is readable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route guards&lt;/strong&gt; — redirect away from a page if &lt;code&gt;canView...()&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buttons/forms&lt;/strong&gt; — disable or hide "Save"/"Edit" controls based on the &lt;code&gt;w&lt;/code&gt; check.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding a brand-new page later (say, "Audits") is the same three steps every time:&lt;br&gt;
add an &lt;code&gt;audits&lt;/code&gt; branch to each role's tree, write &lt;code&gt;canViewAudits&lt;/code&gt;/&lt;code&gt;canEditAudits&lt;/code&gt;&lt;br&gt;
helpers, wire them into the UI. No new pattern to invent, no scattered role list&lt;br&gt;
to update.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't forget the backend
&lt;/h2&gt;

&lt;p&gt;This pattern is just as useful server-side — attach the same permission tree to&lt;br&gt;
the authenticated user/session, and re-run &lt;code&gt;checkAccess&lt;/code&gt; before any write&lt;br&gt;
operation. &lt;strong&gt;The frontend checks are for UX only&lt;/strong&gt; (hiding buttons a user&lt;br&gt;
shouldn't see); the real security boundary is the server independently checking&lt;br&gt;
the same tree before mutating anything. Keep both sides reading the exact same&lt;br&gt;
shape so they never drift out of sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  When this isn't enough anymore
&lt;/h2&gt;

&lt;p&gt;This lightweight pattern is great for typical CRUD-style apps with a handful of&lt;br&gt;
roles and a moderate number of pages/sections. Consider a dedicated&lt;br&gt;
authorization library (like CASL, Casbin, or a policy engine like OPA) once you&lt;br&gt;
need things this simple tree can't express cleanly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Duplicate entries in DB layer&lt;/strong&gt; — Each role will have json structure repeated for all page/section, any new page addition involves changes in all roles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Conditional/attribute-based rules&lt;/strong&gt; — editors can edit only records they&lt;br&gt;
created," not just "editors can edit this section.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explicit deny-overrides-allow precedence&lt;/strong&gt; — right now everything is&lt;br&gt;
additive; there's no way to say "deny this specific case even though the&lt;br&gt;
section is generally writable."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large role/permission matrices&lt;/strong&gt; — if you're maintaining hundreds of&lt;br&gt;
page/section combinations across dozens of roles, dedicated tooling with&lt;br&gt;
testing helpers becomes worth the added dependency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until you hit one of those walls, though: three levels, one tree per role, one&lt;br&gt;
small walker function. That's it.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>javascript</category>
      <category>softwareengineering</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>How do you deal with stress</title>
      <dc:creator>shriramcs</dc:creator>
      <pubDate>Thu, 10 Oct 2024 09:07:33 +0000</pubDate>
      <link>https://dev.to/shriramcs/how-do-you-deal-with-stress-2ik4</link>
      <guid>https://dev.to/shriramcs/how-do-you-deal-with-stress-2ik4</guid>
      <description>&lt;p&gt;"How do you deal with stress" at work?&lt;/p&gt;

&lt;p&gt;This was the question asked to me in a recent interview. I look at them as honestly as possible to introspect myself and answer. I don't shy away from thinking out loud. Interviews are a very beautiful experiences to introspect on yourself about your technical understanding, project development and other soft skills.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is how I answered.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We feel stressed when there is a deadline for a delivery. It is with the individual to handle the stress, in my case, I look at it as another time period I should be able to finish my work. I consider it as seriously as possible, yet, I work in my own pace, making a constant progress at the task in hand.&lt;br&gt;
Important things to note in a stressful environment is or in other words, how not to feel stressed is, to focus only on one thing which is of most important and keep other things aside.&lt;/p&gt;

&lt;p&gt;A generic work involves complete attention no matter what is the deadline for delivery. we do have daily stand ups and to report the progress, the hurdles on the way for the manager to handle the needle for deadline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good manager&lt;/strong&gt;, sets a practical dead line and allows team to work on their own pace and team members are not supposed to deviate from that. Also, a good manager absorbs the progress and sets internal target for himself to have a clear communication with their higher management.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To refocus on the stress part, I feel it is with individual to look at what is causing the stress in them. A fear of not completing the work, A fear of getting a bug out of their deliveries. We live in the future and that causes stress.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Best way to handle this is to look at the complexity of the task, try to create milestones and see if you are getting their as expected or else, report it to team about the progress.&lt;/p&gt;

&lt;p&gt;I'm sure I spent most of my time explaining this to my interviewer, I enjoyed introspecting myself in a situation about how would I really do it.&lt;/p&gt;

&lt;p&gt;Two questions for you.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How do you handle stress at work?&lt;/li&gt;
&lt;li&gt;How do you answer if it was asked for you in an interview?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Leave me a comment! &lt;/p&gt;

</description>
      <category>interview</category>
      <category>career</category>
    </item>
    <item>
      <title>How I Doubled My Salary in 1.5 Years: My Developer Journey Through Job Switches and Career Growth</title>
      <dc:creator>shriramcs</dc:creator>
      <pubDate>Fri, 20 Sep 2024 11:31:09 +0000</pubDate>
      <link>https://dev.to/shriramcs/how-i-doubled-my-salary-in-15-years-my-developer-journey-through-job-switches-and-career-growth-3k46</link>
      <guid>https://dev.to/shriramcs/how-i-doubled-my-salary-in-15-years-my-developer-journey-through-job-switches-and-career-growth-3k46</guid>
      <description>&lt;p&gt;Hello, I'm Shriram Sapparad, a software engineer focused on the frontend of web application development at Ikea, Sweden.&lt;br&gt;
I would like to share my story about how I achieved both career growth and financial stability in the early days of my career.&lt;/p&gt;

&lt;p&gt;TLDR: Work on the opportunities, ask for a salary hike or promotion  if it is in scope in current org else switch job.&lt;/p&gt;

&lt;p&gt;At the end of 2014, I made my first job switch, moving from Tata Consultancy Services (TCS) to Société Générale. After working in IT for five years, I felt it was time for a change. It was also the beginning of the front-end development boom, and I decided to learn Angular for a new company project. I worked day and night on this exciting project because I enjoyed it so much.&lt;/p&gt;

&lt;p&gt;That same year, I also got engaged, and things started moving quickly in my life in 2015. I was lucky to have a supportive team and great colleagues who helped me not only improve my technical skills but also advised me on financial planning, especially as I was preparing to start my own family.&lt;/p&gt;

&lt;p&gt;Within a year, I switched jobs again, this time to Thermo Fisher Scientific. Over a period of 1.5 years, with two job switches and improving my tech skills, I was able to double my salary by 100%.&lt;/p&gt;

&lt;p&gt;After my marriage, I was managing some financial responsibilities. I was paying off a marriage loan and also supporting my family back in my hometown by sending a monthly amount to my father. Despite these obligations, I didn’t want to cut back on my expenses, so I started looking for ways to earn more.&lt;/p&gt;

&lt;p&gt;I began reading stories on Quora about how to get into top IT companies that pay well. However, I realized that top-tier tech companies like FANG (Facebook, Amazon, Netflix, Google) weren’t the right fit for me. I didn’t see myself as someone who would build innovative tech, but rather as someone who develops solutions using the best tools available.&lt;/p&gt;

&lt;p&gt;Eventually, I found my place in financial and IT companies. I prepared well and was able to crack an interview with JPMorgan Chase. This marked a new phase in my tech career, where I achieved both career growth and financial stability.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>career</category>
      <category>frontend</category>
      <category>devjournal</category>
    </item>
  </channel>
</rss>
