flask-security icon indicating copy to clipboard operation
flask-security copied to clipboard

Issue with `registerable.register_user` function change

Open richard-to opened this issue 5 years ago • 2 comments

I've been working on upgrading from Flask Security 3.0.0 to Flask Security Too 3.4.2.

There was change in this commit (https://github.com/Flask-Middleware/flask-security/commit/3c5fd22bf45c21d769544344d985df67ffbf2b09#diff-2e9556678333fc9e7dfe58473f411bb4) that changed how the register_user function works. Instead of a dict-like object, it now takes in the register form, which is fine.

However I'm encountering a problem with it since my RegisterForm includes some custom fields that belong to the user model, but can't be processed correctly since it's a SQLAlchemy 1 to many field, much like roles. So that will break the form.

My current solution is to change the name of the field to something else that doesn't match the model field. So I can handle the processing after calling the register function.

Granted in the old version where register_user accepted a dict was not much better, since I had to manually remove this field from to_dict()

Example (psuedocode):

User:
   # normal fields
   hobbies # which is a 1 to many relationship

Hobby:
  id
  name

RegisterForm(FlaskForm, RegisterFormMixin, UniqueEmailFormMixin, NewPasswordFormMixin):
  hobbies = MultiSelectField()

richard-to avatar Jun 05 '20 23:06 richard-to

Interesting - do you have any thoughts on a better solution?

jwag956 avatar Jun 06 '20 15:06 jwag956

At the moment I do not have a better solutions in mind. But here are some other options I considered.

One option is in my register form, I guess I could create a custom WTForm field that returned my Hobbies as Hobby models.

Since I use SQL Alchemy, for this particular use case, I think I could use the SQL Alchemy Association Proxy (https://docs.sqlalchemy.org/en/13/orm/extensions/associationproxy.html)

Another option would be to add a "excluded_fields" parameter to register_user, which would allow me to specify "hobbies" as a field to ignore when creating the user.

A fourth option I considered is going back to allowing a dict. One of the benefits is that it allows me to pre-process the fields before passing them into the registration form. For example, I could convert my hobbies to models first. It allows me to bypass the form. I have also have use case where I register some user accounts in bulk.


Ultimately, I ended up creating my own version of the register_user function that accepted a dict, so sort of reverted to the previous functionality. I'm not sure that's the best solution in general, but for my very specific use case that was the best option for me.

richard-to avatar Jun 06 '20 19:06 richard-to