Absinthe Schema Type / Database Mismatch Errors / Warnings?

I have a custom scalar type, e.g. ‘Email’ which ensures anything going into the email field of my ‘User’ DB table is a well formed email address.

But just for fun I overwrote an email field with a random string (i.e. not an email address).

Even though my user function requires an ‘Email’ type returned, it doesn’t even squeek when gobble-dee-gook comes back…

Am I doing something wrong? Perhaps this is not a part of the GraphQL spec?

Seems odd however… I prefer stubborn type systems I suppose… Any thoughts?

Hey there!

Can you provide a bit more information? Specifically, what do you mean by “I overwrote an email field”. Are you saying that you changed it in the database directly?

Can you supply the code you have for your custom scalar?

At the end of the day though if you’re writing a custom scalar it’s the job of that scalar to validate out going data as well as incoming data. Absinthe can’t magically know that the string isn’t a valid email.

Aha, this could totally be my problem somehow.

Yep, I am manually going into the DB, malforming the email address etc.

Type checking works like a charm with mutations though!

object :user do
    ...
    field :email, non_null(:email)

  scalar :email, description: "A Valid Email Address" do
    parse &validate_email(&1.value)
    serialize &id(&1)
  end

  # ensure that the email looks valid
  def validate_email(email) when is_binary(email) do
    case Regex.run(~r/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/, email) do
      nil ->
        :error
      _ ->
        {:ok, email}
    end
  end

This regex will miss some valid E-Mail addresses.

For note, if you assume pretty much anything other than it is a string of at least length 2 that contains at least one @ then you will probably get it wrong. If you really want to make sure an email address is valid then you should connect to the remote server (which could be dot-less) and ask it.

I think the ‘proper’ regex validator for EMail is something on the order of a few thousand characters long otherwise.

1 Like

That regex will deny valid TLDs like museum, hamburg and many other.

Also it will deny puny-coded domains.

In summary that are quite a lot lost customers…

1 Like

Haha, thanks guys. Luckily we have a dozen customers and we know their email addresses upfront : ))

I doubt the regex is the nub of my problem - will look into it more today.

OK, I came up with a simpler example.

  scalar :password, description: "A Valid Password (i.e. over 6 characters long)" do
    parse &validate_password(&1.value)
    serialize &id(&1)
  end

  def validate_password(password) when is_binary(password) do
    if (String.length password) >= 6 do
        {:ok, password}
    else
        :error
    end
  end

If I change the password string in the DB table to a single character for example, reload, I see the single character in JSON.

(Usually the password is hashed, this is really just for expository purposes).

I noticed that Enum Types type check flawlessly. So it’s really just the custom Scalar case so far that doesn’t error correctly.

Can anyone else reproduce, or show me an example where iffy Scalar types will produce an error when returned?