bolt / users

Bolt users extension.
MIT License
8 stars 7 forks source link

Appearance customization #12

Open labrador-gibraltar opened 3 years ago

labrador-gibraltar commented 3 years ago

Hello! I'm trying to customize HTML returned by login_form() function. This needs some attributes inside tags, like class, id etc. But there are only label parameters available, as long as for login_form_username, login_form_password functions made for customization. Of course, I can write my own html/twig as I want, but how do I retrieve postUrl and redirectField that are used in src/Twig/LoginFormExtension.php ? Sorry if this is a dumb question, I'm new to BoltCMS. Should I rewrite named class or there is more elegant way?

andriusign commented 3 years ago

Hello! I'm trying to customize HTML returned by login_form() function. This needs some attributes inside tags, like class, id etc. But there are only label parameters available, as long as for login_form_username, login_form_password functions made for customization. Of course, I can write my own html/twig as I want, but how do I retrieve postUrl and redirectField that are used in src/Twig/LoginFormExtension.php ? Sorry if this is a dumb question, I'm new to BoltCMS. Should I rewrite named class or there is more elegant way?

Hello. I am new to Bolt CMS too, made a simple form in twig and styled it. Redirect path can be added like this:

<form action="/bolt/login">
...
<input type="hidden" name="_target_path" value="/page/profile">

But it only seems to be working for login form. Can't figure out why it's not working for registration form. Neither can I figure out how to display errors if the registration/login fail. Form does not seem to provide any data on this.

labrador-gibraltar commented 3 years ago

I copied class LoginFormExtension from extension folder into App\Extension\users\Twig (maybe better would be extend) after that I changed new TwigFunction('login_form', [$this, 'getLoginForm'], $safe), to new TwigFunction('my_login_form', [$this, 'getLoginForm'], $safe), and removed declaration for login_form_username etc Then I changed html generated by these funcs to my needs. And used my_login_form in template. And somehow it works for me :)

Regarding error messages, I haven't fixed them yet, but I noticed, then when you, say, send wrong creds in FE form and in same session (same browser window) open BE login form (/bolt/login), it shows error message for FE form, so you can try to peek into it's code to find out how's it retrieved. And if you succed, please let me know, for it waits for me too...

I-Valchev commented 3 years ago

Hi @labrador-gibraltar and @andriusign ,

Just to confirm what @andriusign already mentioned, indeed you can build a custom form if you would like to do further custom work. You can generate a path to the bolt_login route like so:

<form action="{{ path('bolt_login') }}>
...

Hope this helps! Let me know if you have other questions.

labrador-gibraltar commented 3 years ago

@I-Valchev, thank you! There are few more questions about the extension: 1) in file bolt-usersextension.yaml setting groups.ROLE_NAME.redirect_on_login doesn't seem to be applied (default.redirect_on_login does) 2) Is there some working project which uses the extension? I'd like to see config/routes.yaml and config/packages/security.yaml Because it was tricky to make login/logout routes for FE end BE work in same time. I had to add dedicated firewall for /bolt/logout URL, which seems like a hack. Is it possible that the issue appeared because I've uncommented content_seo route in routes.yaml? And, maybe, this is the cause for: 3) allow_for_groups setting for content type doesn't work, protected page is shown for an anon. Debugger shows, the execution desn't even enter AccessAwareController::applyAllowForGroupsGuard() UPD Found out that bolt routes record, record_locale have same names as extension ones in ProtectedDetailController. I think the latter should be renamed into record_custom, record_locale_custom just like in ProtectedListingController. As a temp fix, placed

users_extension_controllers:
  resource: '../vendor/bolt/users/src/'
  type: annotation

in the end of routes.yaml

I-Valchev commented 3 years ago

hi @labrador-gibraltar ,

  1. The setting should be applied, if it does not work, I'd suggest creating an issue for it. And if you can find out why it fails, even better you can create a PR that fixes it :-)

  2. I don't know of an open-source project that does it, and I myself don't have a project that uses it. I know @crim3hound used to work on this extension a lot, perhaps he has some insights to share?

  3. I am sure that it used to work before, could be that with some new additions we introduced a bug. As with 1, please feel free to submit an issue/PR if it doesn't behave as you'd expect.

crim3hound commented 3 years ago

Thanks @I-Valchev for the mention and my apologies for the late response.

@labrador-gibraltar, for my particular use case (still under active development, but you are free to test it out at https://demo.raymusumba.com), the extension does what it is supposed to, and I think it does the job well. As far as a logout route is concerned, which you will see us discussing in Issue #11, there may be no easy solution at the moment because I believe this extension is tied to the same authentication flow used for the BE, right @I-Valchev?

That said, I turned to the extension's logic to handle routing based on auth status, for example, there is a route named extension_frontend_user_profile. In order to access that route, a user has to be logged in, which we test for in FrontendUsersProfileController.php (I believe this is also merged as a fix the above reference issue, where we added a redirect_on_session_null to the extension config). With that logic in place, it was of little consequence to change L33 of my config/packages/security.yaml file as follows:

logout:
     handler: Bolt\Security\LogoutListener
     path: bolt_logout
     target: extension_frontend_user_profile # (redirection to frontend login will be handled by extension)
     #target: bolt_login # (redirects to backend login - we want to avoid this for frontend users)

So practically, if you set something like redirect_on_session_null: /login in your extension config, and you change the security firewall as above, when a user logs out using the internal logout route, i.e. {{ path('bolt_logout') }}, there will be no active session and they will be redirected to the page that you set in your config.

I hope this makes sense? I was trying to work on a logout route for FE users primarily because I wanted to obscure the BE login URL because I always change it for all my projects for security reasons. So FE users don't get to it at all. Feel free to create an account for the project above while I still have it hosted so you can see the flow.

crim3hound commented 3 years ago

PS: @labrador-gibraltar my config/routes.yaml is untouched by the way. A lot of my logic is handled by my extension's config.yaml, in which I have a bunch of custom options set that I am using in my controllers. Also, for your first issue where you say

in file bolt-usersextension.yaml setting groups.ROLE_NAME.redirect_on_login doesn't seem to be applied (default.redirect_on_login does)

you need to make sure your registration form is registering users to that group for the configs to be applied. In my case, for example ROLE_USER is the least privileged user, and I use {{ registration_form(group='ROLE_USER') }} to sign up all new users. ROLE_MEMBER on the other hand is a step above ROLE_USER, and is reserved only for subscribed members, who get prescribed the role after some logic has been passed, e.g. they made a successful subscription payment.

crim3hound commented 3 years ago

@andriusign on this issue you're facing:

But it only seems to be working for login form. Can't figure out why it's not working for registration form. Neither can I figure out how to display errors if the registration/login fail. Form does not seem to provide any data on this.

If you use the registration form as mentioned above, the related settings you set in your config will work. If you really need to customize your form output, perhaps you could look at \src\Twig\LoginFormExtension.php and \src\Twig\RegistrationFormExtension.php to keep things simple and generated dynamically as opposed to hardcoding your forms (and ALWAYS maintain back up copies of the files).

On the feedback, I think you're better off being as obscure as possible. Don't give any leads as to what input is erroneous. 9/10 time it will be feedback about wrong credentials anyway, so if you really want to give that feedback you could find a way to show something like "Invalid username/password" in a toast or something. I would argue that a password reset functionality would take higher precedence. Additionally, you could opt for client-side input validation as well, as I've done with the example at https://demo.raymusumba.com/page/register