|
# MIT License |
|
# |
|
# Copyright (c) 2025 Ahmad Hammad / @afhammad |
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
# of this software and associated documentation files (the "Software"), to deal |
|
# in the Software without restriction, including without limitation the rights |
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
# copies of the Software, and to permit persons to whom the Software is |
|
# furnished to do so, subject to the following conditions: |
|
# |
|
# The above copyright notice and this permission notice shall be included in |
|
# all copies or substantial portions of the Software. |
|
# |
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
# SOFTWARE |
|
|
|
defmodule MyAppWeb.Schema.Middleware.AuthorizedIntrospection do |
|
@moduledoc """ |
|
Disable or restrict schema introspection to authorized requests |
|
""" |
|
@behaviour Absinthe.Plugin |
|
|
|
@impl Absinthe.Plugin |
|
def before_resolution(%{context: %{admin: true}} = exec), do: exec |
|
|
|
def before_resolution(exec) do |
|
if Enum.find(exec.result.emitter.selections, fn %{name: field_name} -> |
|
Macro.underscore(field_name) == "__schema" |
|
end) do |
|
%{ |
|
exec |
|
| validation_errors: [ |
|
%Absinthe.Phase.Error{message: "Unauthorized", phase: __MODULE__} |
|
] |
|
} |
|
else |
|
exec |
|
end |
|
end |
|
|
|
@impl Absinthe.Plugin |
|
def after_resolution(exec), do: exec |
|
|
|
@impl Absinthe.Plugin |
|
def pipeline(pipeline, _exec), do: pipeline |
|
end |
Thank you! This is fantastic!
Just a quick follow up question...
Looking at the revisions, I am having a hard time determining the motivation for moving from
String.downcasetoMacro.underscorein thebefore_resolutionfunction. Is there some specific edge case that counts for? I see that it converts things like_Schemato__schema, but I wasn't able to find anything in GQL spec about using capital letters for reserved words.