موفق نبود Ecto دراعتبار سنجی UUID ارسالی

با درود خدمت دوستان عزیز . یک مشکلی برای من پیش اومده اونم زمانی اتفاق می افته که کاربر بخواد از هدف پیش تعیین شده یک داده ای بد به من ارسال کنه که از جمله این داده می تونه :

کلید خارجی که UUID هست باشه . به عنوان مثال کاربر داره پستی رو ارسال می کنه که باید به مجموعه رلیشن بشه و UUID مجموعه داخل پست ثبت بشه ولی اگر کاربر یک کلمه حذف کنه ارور ۵۰۰ درج می شه

این مطلب در اینجا هم ارسال کردم :

در اینجا بهم پیشنهاد دادن من ارور خاص خودم رو بنویسم و UUID رو قبل از insert کردن چک کنم. آیا شما موفق این کار هستید؟

به روز رسانی

راه حلی که من بر اساس صحبت این عزیزان خودم پیشنهاد کردم اینه

از پترن استفاده کردم بجای rase .

   def create_cms_post(conn, %{"title" => _title, "status" => _status, "post_type" => _post_type, "download_ext_link" => _download_ext_link, "price" => _price, "pic_x1_link" => _pic_x1_link, "pic_x2_link" => _pic_x2_link, "pic_x3_link" => _pic_x3_link, "group_acl" => _group_acl, "description" => _description, "changelog" => _changelog, "changelog_category" => _changelog_category, "plugin" => _plugin, "plugin_category" => _plugin_category, "discourse" => _discourse, "discourse_link" => _discourse_link, "screen_shot" => _screen_shot, "screen_shot_category" => _screen_shot_category, "learn" => _learn, "learn_category" => _learn_category, "seo_tag" => _seo_tag, "seo_alias_link" => _seo_alias_link, "seo_words" => _seo_words, "seo_description" => _seo_description, "seo_language" => _seo_language, "seo_language_link" => _seo_language_link, "cms_post_category_id" => cms_post_category_id} = allreq) do
      create_post(conn, allreq, Ecto.UUID.cast(cms_post_category_id))
   end

   defp create_post(conn, _allreq, :error) do
      conn
      |> put_status(403)
      |> json(%{error_code: "403"}) 
   end

   defp create_post(conn, allreq, {:ok, _}) do
      create_cms_posts = case PostQuery.insert_post(allreq) do
            {:ok, _post} 		   -> 
               conn
               |> put_status(200)
               |> json(%{message: "The post has been created."})            
            {:error, _changeset}  ->
               conn
               |> put_status(403)
               |> json(%{error_code: "403"})
         end
      create_cms_posts     
   end

سلام، ارور ۵۰۰ خیلی کلیه! اگر میشه ارور اصلی رو بده. درضمن یوزری که دیتا رو دستکاری کنه باید این ارورو بگیره دیگه. میتونی length فیلد مورد نظرو ولیدیت کنی.
بنظر میاد شما در اصل ارورو مخفی میکنی، امیدوارم در دیباگ کردن مشکل ساز نشه و اینکه انگار 422 بهتر باشه.
422 Unprocessable Entity

من وقتی api طراحی میکنم گاهی یه سری به لینک زیر میزنم

1 پسندیده

میخواستم اونجا پاسخ بدم اما گفتم بیام همینجا :smile:
چرا fail fast بمب ساعتیه؟ کل فلسفه erlang بر مبنای let it crash پایه گذاری شده. البته شما باید در نهایت ولیدیت کنی اما منظور من اون جمله شما بود.

تا زمانی که exception در خاموشی مخفی نشه مشکلی پیش نمیاد

1 پسندیده

درود خدمت توماج عزیز .

ارور در اون پست الکسیر قرار داده بودم شرمنده یادم رفت اینجا هم بزارم ارور به شرح زیر هست

** (exit) an exception was raised:
    ** (Ecto.ChangeError) value `"a863228-727c-4cf3-93f5-9b2f79df1288"` for `TrangellCmsService.Cms.Db.Post.cms_post_category_id` in `insert` does not match type :binary_id

موضوع این هست که Ecto انگار نمی

تونه درک کنه که UUID مشکل داره یا نه . مثلا اگر کاربر یک حرف رو از کل UUID حذف کنه اون به صورت کامل یک ارور ۵۰۰ خوشگل می زنه تو صورت ترمینال :grin:

دم شما گرم خیلی دنبال این لینک می گشتم خیلی لطف کردی همیشه می خواستم برم پیداش کنم یادم می رفت مشغول کدنویسی می شدم .

توماج جان من ارور رو مخفی نمی کنم در حقیقت من دارم قبل از ارسال به Ecto در خود کنترلر چک می کنم که آیا این UUID ولید هست یا خیر اگر ولید بود که بقیه کارو انجام بده اگر خیر که اروری به کاربر نشون بده مثلا ۴۰۰

نمی دونم کجا خونده بودم اصلا یادم نمی یاد که می گفتند raise نباید تا زمانی که واقعا نیاز بشه استفاده نشه . خواستم جمله هم بنویسم خفن باشه :grin: گفتم بهترینش همنه

فقط توماج جان من این بخش از صحبت شما رو متوجه نشدم می شه توضیح بدید البته اگر زحمتی نیست .


این تابع Ecto.UUID.cast کلا یا :error خروجی می ده یا می یاد {:ok, uuid} من فکر کردم از خود تابع اصلی استفاده کنم خیلی بهتر از raise‍ که کل ارور بگیره و به قول شما مخفی کنه چون انگار داره صورت مسئله رو پاک می کنه ولی تابع اصلی خوب بررسی می کنه اوکی هست یا نیست

ممنون توماج جان شما و سام عزیز همیشه پست هارو همراهی می کنید بنده خیلی از شما ها یاد گرفتم . دیگه نمی دونم چطور تشکر کنم . امید وارم همیشه در سلامتی باشید

منابع :
https://hexdocs.pm/ecto/Ecto.UUID.html#dump/1

1 پسندیده

فکر کنم منظورش rescue بوده نه raise :wink:

1 پسندیده

آخه به من این لینک رو داده بود.

 defp dump_field!(action, schema, field, type, value, adapter) do
    case Ecto.Type.adapter_dump(adapter, type, value) do
      {:ok, value} ->
        value
      :error ->
        raise Ecto.ChangeError,
              "value `#{inspect value}` for `#{inspect schema}.#{field}` " <>
              "in `#{action}` does not match type #{inspect type}"
    end
  end

بعد من باز بهش گفتم این مثل بمب ساعتی می مونه بازم جواب داد

I actually use raise quite often (“fail fast” and all that). I wouldn’t call it a time bomb …
1 پسندیده

آها اون موردی که فکر می کردم رو می فرمایید که از rescue استفاده نکنم

1 پسندیده

تا جایی که امکان داره از rescue استفاده نکن, اگر هم استفاده میکنی exception کاملا تعریف شده و صریح (explicit) باشه.
منظورم اینه که error type از پیش درنظر گرفته بشود.

raise BusIsLateError(reason: "Bus driver was using Telegram!")

rescue BusIsLateError => e
log e.reason
get_taxi()
2 پسندیده