archtechx / airwire

A lightweight full-stack component layer that doesn't dictate your front-end framework
https://archte.ch/blog/introducing-airwire
MIT License
201 stars 9 forks source link

Question - How to handle auth and policy related validations? #14

Open bobmulder opened 3 years ago

bobmulder commented 3 years ago

Hi there!

When I stumbled across Airwire, my developer-heart made a little jump of joy. This seems to be the library I've been thinking of so many times... Inertia.js seems to be too much, Livewire 'forces' me to use alpine (I know this aint completely true, but nevermind), but this library just does the wiring, and it lets me be in control of my js side and backend side. Awesome!

My current api-like controllers which can be seen as the soon-deprecated-pre-airwire-component-classes, always handle some business-like validation, and auth related validation. When something goes wrong on that endpoint, I return a 400 error or something, and that's it.

But.... How do we handle such cases in Airwire? To make things more specific:

  1. How do we handle Laravels policy validation in Airwire components?
  2. How do we handle authentication related validation in Airwire components?
  3. How do we handle custom business logic validation in Airwire components, and what should be returned when something goes wrong (the 400 status code)?

Thank you for reading and commenting :)

Bob

stancl commented 3 years ago

If the policy validation you're referring to uses the Laravel validator, it will work the same as input validation.

Exceptions are handled in a very specific way:

Maybe it could be nice to be able to define something like "if AuthorizationException is encountered, share it with the frontend even in production, but only use this data". Because sending the whole exception is obviously bad, as it includes the stack trace, but sending nothing is probably not ideal in cases of authorization etc.

You could do something like:

if (! auth()->user()->can('edit', $post)) {
    $this->meta('alert', 'You cannot do this.');

    return;
}

And handle that on the frontend:

Airwire.watch(response => {
    if (response.metadata.alert) {
        alert(response.metadata.alert);
    }
});

But I agree that having a way to handle abort-type behavior automatically would be ideal.

bobmulder commented 3 years ago

Thank you for getting back @stancl. Happy to hear there are some thoughts about this topic.

In the docs I read about the AirWirePromise returned by e.g. a submit() function call. I've been thinking about this: don't you want to throw exeptions in those functions (like the Laravel controller will on policy validation), which can be handled in your javascript with catch-ing the promise?

I've been too lazy to try this, but sounds like it 'should be'.

However, still need some thoughts on the initializing part of the component...

I'll setup a demo myself this weekend :)

stancl commented 3 years ago

Ah right, forgot to mention that. Yes, you can use catch() for exceptions.

But right now I'm not sure if they're included in prod. It should probably leave out the stack trace, but keep the exception message, if a custom exception is used

bobmulder commented 3 years ago

Hi there @stancl,

I tried to do some testing, but I can't get Airwire working with Vue 3...

image

It seems that Vue Devtools throws some errors. Airwire does not make any call.

A public POC is available here: https://github.com/bobmulder/airwire-poc

Are you able to give it a shot? Would love to do some testing with Airwire with Vue 3 :)

stancl commented 3 years ago

Have you seen the demo? It uses Vue 3

bobmulder commented 3 years ago

Snap! Forgot about that one... But it doesn't use the composition API 🤓

stancl commented 3 years ago

I don't think there should be any differences really, the reactivity logic is the same.

But yes, I'd like to have a few more demos in the near future.