<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="84532" data-post-id="84532">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="BartOtten" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/BartOtten/120/25440_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  BartOtten
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I cleaned up the code quite a bit, might even try to use it to protect my latest project just to find all the flaws. Here are some details:</p>
<p>def() is overridden so it sends and receives information about the current Module, Fuction and Arity (m/f/a) and wraps the ‘real body’ in a Task so it has it’s own process with inbox. Each function called in the wrapped function will receive a message with the m/f/a that called the function.</p>
<p>Knowing the current m/f/a and the calling m/f/a, a map is created and passed to the authorization function which you write yourself. As it’s a map, it’s easy to do pattern matching! The examples don’t show it, but you are able to protect context (Module) borders, restrict calls to <code>"update_" &lt;&gt; _</code> for users (for every function of the Module) or giving admins a wildcard with <code>def authorize(%{args: %{context: %{role: :admin}}}), do: :ok</code></p>
<p>Removed: If a function calls itself (see: get_post/2) this is detected and authorization will be skipped.<br>
Added: Sounds like a rule to me! <code>def authorize(%{mod: mod, func: func, arity: arity, calling_mod: mod, calling_func: func,  calling_arity: arity}), do: :ok</code> does the job as expected. Removed the loop detection.</p>
<p>Authorization map:</p>
<pre><code> auth_map = %{
          calling_mod: calling_mod,
          calling_func: calling_func,
          calling_arity: calling_arity,
          mod: current_mod,
          func: current_func,
          arity: current_arity,
          args: current_args
        }
</code></pre>
<p>The rules:</p>
<pre><code>defmodule Main.Authorizer do

  def authorize(auth_map \\ %{})

  # update post rules
  def authorize(%{func: "update_post", args: %{context: %{role: :admin}}}), do: :ok

  def authorize(%{func: "update_post", args: args}) do
    case Main.get_post(args[:id], args[:context]) do
      :unauthorized -&gt; :unauthorized
      post -&gt; post[:author_id] == args[:context][:user_id]  &amp;&amp; {:ok, post} || :unauthorized
    end
  end

  # get post rules
  def authorize(%{func: "get_post", args: %{context: %{role: :admin}}}), do: :ok

  def authorize(%{func: "get_post", args: args}) do
    post = Main.get_post(args[:id], args[:context])
    post[:author_id] == args[:context][:user_id]  &amp;&amp; {:ok, post} || :unauthorized
  end

  # sink
  def authorize(_), do: :unauthorized
end
</code></pre>
<p>The result (User 124 is author of Post 2):</p>
<pre><code>iex(auth@127.0.0.1)1&gt; Main.update_post(2, %{content: "Updated content"}, %{user_id: 124, role: :user})
[info] Main.get_post/2 requested authorization to access Main.get_post/2. [SKIPPED AUTH]
[info] Main.update_post/3 requested authorization to access Main.get_post/2. [ACCESS GRANTED]
[info] An unknown function requested authorization to access Main.update_post/3. Are you using IEX?. [ACCESS GRANTED]
{:ok, %{content: "Updated content"}}
iex(auth@127.0.0.1)2&gt; Main.update_post(2, %{content: "Updated content"}, %{user_id: 123, role: :user})
[info] Main.get_post/2 requested authorization to access Main.get_post/2. [SKIPPED AUTH]
[info] Main.update_post/3 requested authorization to access Main.get_post/2. [ACCESS DENIED]
[info] An unknown function requested authorization to access Main.update_post/3. Are you using IEX?. [ACCESS DENIED]
:unauthorized
iex(auth@127.0.0.1)3&gt; Main.update_post(2, %{content: "Updated content"}, %{user_id: 123, role: :admin})
[info] An unknown function requested authorization to access Main.update_post/3. Are you using IEX?. [ACCESS GRANTED]
{:ok, %{content: "Updated content"}}
iex(auth@127.0.0.1)4&gt;
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="84532" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-to-get-name-of-calling-module-and-or-function/14539/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-84532" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="84532"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-solved cat-solved" title="Marked as solution"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>