zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

sign.ex (2026B)


      1 # Zenflows is designed to implement the Valueflows vocabulary,
      2 # written and maintained by srfsh <info@dyne.org>.
      3 # Copyright (C) 2021-2023 Dyne.org foundation <foundation@dyne.org>.
      4 #
      5 # This program is free software: you can redistribute it and/or modify
      6 # it under the terms of the GNU Affero General Public License as published by
      7 # the Free Software Foundation, either version 3 of the License, or
      8 # (at your option) any later version.
      9 #
     10 # This program is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 # GNU Affero General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU Affero General Public License
     16 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
     17 
     18 defmodule Zenflows.GQL.MW.Sign do
     19 @moduledoc """
     20 Absinthe middleware to verify GraphQL calls.
     21 """
     22 
     23 @behaviour Absinthe.Middleware
     24 
     25 alias Zenflows.Restroom
     26 alias Zenflows.VF.Person
     27 
     28 @missing_headers_auth_call "couldn't aunthenticate: zenflows-user and/or zenflows-sign headers are missing"
     29 
     30 @impl true
     31 def call(res, _opts) do
     32 	if res.context.authenticate_calls? do
     33 		with {:ok, username, sign, body} <- fetch_ctx(res),
     34 				{:ok, per} <- fetch_user(username),
     35 				:ok <- verify_gql(body, sign, per) do
     36 			put_in(res.context[:req_user], per)
     37 		else x ->
     38 			Absinthe.Resolution.put_result(res, x)
     39 		end
     40 	else
     41 		res
     42 	end
     43 end
     44 
     45 defp fetch_ctx(res) do
     46 	case res.context do
     47 		%{gql_user: username, gql_sign: sign, gql_body: body} ->
     48 			{:ok, username, sign, body}
     49 		_ -> {:error, @missing_headers_auth_call}
     50 	end
     51 end
     52 
     53 defp fetch_user(username) do
     54 	case Person.Domain.one(user: username) do
     55 		{:ok, user} -> {:ok, user}
     56 		_ -> {:error, "user not found"}
     57 	end
     58 end
     59 
     60 defp verify_gql(body, sign, per) do
     61 	case Restroom.verify_graphql(body, sign, per.eddsa_public_key) do
     62 		:ok -> :ok
     63 		{:error, reason} ->
     64 			{:error,
     65 			"""
     66 			authentication error.
     67 
     68 			details:
     69 
     70 			#{reason}
     71 			"""}
     72 	end
     73 end
     74 end