If I set the user image as required (field name: "user_picture"). Then I cannot login via facebook. There comes the error:

Creation of user account failed: This value should not be null (I have translated the last part from german into english).

However, if I set the user_picture field as "not" required, I can login succesfully via facebook and the user picture is retrieved. What I need to do, to keep the user picture required in the user profile field settings and still be able to login via facebook? Is this a bug in the "Simple FB Connect" module?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Peter Majmesku created an issue. See original summary.

Peter Majmesku’s picture

Issue summary: View changes
Peter Majmesku’s picture

This is a bug in the module. Because the user is firstly created (modules/contrib/simple_fb_connect/src/Controller/SimpleFbConnectController.php:153) in and afterwards the user picture is added (modules/contrib/simple_fb_connect/src/Controller/SimpleFbConnectController.php:157). But this must happen at once, to respect required fields.

See in returnFromFb():

    if ($drupal_user = $this->userManager->createUser($fb_profile->getField('name'), $email, $fbid)) {

      // Download profile picture for the newly created user.
      if ($picture_url = $this->fbManager->getFbProfilePicUrl()) {
        $this->userManager->setProfilePic($drupal_user, $picture_url, $fbid);
      }

You should not call the createUser(); method in createUser(); but rerutn the user object to call the save() method at the end of returnFromFb().

Peter Majmesku’s picture

I have created a patch, which extends SimpleFbConnectUserManager::createUser() with the ability to add a facebook user profile image to the drupal user profile, by respecting the required field.

masipila’s picture

Status: Active » Needs review

Setting to needs review to trigger the testbot.

Status: Needs review » Needs work

The last submitted patch, 4: fb-login-user-image-required-field-2874179.patch, failed testing.

masipila’s picture

Hi @Peter Majmesku,

Thanks for reporting this. Could you please re-submit your patch according to Drupal patch standards so that it would apply correctly? And at the same time, please ensure that your patch is against the latest DEV as the dev is several commits ahead of 8.x-3.0 (this issue is marked as 8.x-3.0 so I assume your patch is against 8.x-3.0 and not 8.x-3.x-dev)

Cheers,
Markus

Peter Majmesku’s picture

Hi Markus,

the first patch was against the stable version. Here I have made one against the latest 8.x-3.x dev version, which I have cloned via Git. I have created the patch the way described here: https://mobilefish.de/creating-patch-git. It should be good now.

Regards

Peter Majmesku’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 8: fb-login-user-image-required-field-2874179.patch, failed testing.

Peter Majmesku’s picture

Made fourth param ($pictureUrl) optional for tests.

Peter Majmesku’s picture

Peter Majmesku’s picture

Peter Majmesku’s picture

Peter Majmesku’s picture

masipila’s picture

I was checking this earlier today before your latest patch updates. We have here a conceptual challenge.

First of all, we do not download the Facebook default silhouette picture if the user has not set a profile pic on Facebook. In other words, there is no file to be added as the Drupal user's profile pic.

Second, the API call to get the user's profile pic can fail in a rare corner case even if the user's profile could be read. Also in this case we would not have any file to be added.

The second one is quite theoretical corner case but the first one is by design. So setting the user's profile pic as required is quite difficult...

Markus

Peter Majmesku’s picture

First of all, we do not download the Facebook default silhouette picture if the user has not set a profile pic on Facebook. In other words, there is no file to be added as the Drupal user's profile pic.

Well, I have a site where I require that people register with a profile image only. You can imagine that a profile with an image is far more valueable than one, without an image. So I see here a lack of functionality. There should be the ability to display an image to the user, that an image is required.

The second case for me is just a bug.

If you still insist, then close this issue. I have what I needed.

masipila’s picture

I did understand that your site requires a profile picture and I see the rationale why some sites are requiring it.

However, the second scenario can be caused by a network issue for example or Facebook API to be unavailable at the time of the second API call where we try to get the URL for the profile pic. What would be your suggeetion to handle this error situation or should we just not create the Drupal user record if this happens?

What would you suggest to happen if the user has not added a profile pic on Facebook? Should we not create a Drupal user and show a message for the user to add a pic on Facebook first?

Cheers,
Markus

Peter Majmesku’s picture

However, the second scenario can be caused by a network issue for example or Facebook API to be unavailable at the time of the second API call where we try to get the URL for the profile pic. What would be your suggeetion to handle this error situation or should we just not create the Drupal user record if this happens?

You have this scenario often when you are sitting in a train and getting into an area without a communication spot. Then all sites like facebook, google etc. report you an error, when the transferred data was incomplete and you get a message like: "Your data could not be submitted. Please try again." Another - more expensive - option would be, to make the request via JavaScript, so the script would submit the request again from the client side, if the request could not be successfully finished. But I think that a simple error would do the job to be compatible to the fieldable drupal user profile.

If the user has just no facebook profile image, then there should be a specific error message: "We can only accept user registrations with a user profile image. Please upload a profile image at facebook or use our registration form."

masipila’s picture

If the user has just no facebook profile image, then there should be a specific error message: "We can only accept user registrations with a user profile image. Please upload a profile image at facebook or use our registration form."

This message that complains about the missing profile pic needs to be shown only when the Drupal user pic is required. Sites that don't have the user pictures defined as required should accept the registration without the picture.

Are you able to update your patch with this check applied? This same handling covers also the rare corner case where profile pic url query fails.

Markus

masipila’s picture

To continue: I'd assume that we can figure out if the field is required using EntityFieldManager the same way how we check the directory for user pictures in SimpleFbConnectUserManager::getPictureDirectory

Peter Majmesku’s picture

I have currently only a small use case for the Simple FB Connect module. If my project will grow, I will participate more in the project. Right now I must set my priorities.

Peter Majmesku’s picture

The patch I have provided so far, will already enrich the module.

masipila’s picture

Hi again,

Just be aware that if you use your patch as it is

  • Your user creation will fail if the user does not have a picture on Facebook
  • The file will not have the owner set up correctly

It is of course up to you to judge if these are acceptable on your site and use case.

If somebody wishes to continue with this issue, we need to properly handle a couple of scenarios so that this could be committed.

Pre-requisite: we need to add a new method to SimpleFbConnectUserManager that checks if user pictures are required.

  protected function userPictureRequired() {
    $field_definitions = $this->entityFieldManager->getFieldDefinitions('user', 'user');
    if (isset($field_definitions['user_picture'])) {
      return $field_definitions['user_picture']->get('required');
    }
    // If user_picture field is not defined, it is not required.
    return FALSE;
  }

Scenarios 1: User pictures are enabled but not required (Drupal default behavior)

Scenario 1.1:

  • User pictures are enabled but not required (Drupal default behavior)
  • API call for getting the Facebook profile picture fails OR the profile picture download fails

Expected behavior for this scenario:

  • Log an error that the API call to read the profile picture failed / file download failed
  • Drupal user's profile picture field is left empty (OK, because the field is not required)

Scenario 1.2:

  • User pictures are enabled but not required (Drupal default behavior)
  • API call for getting the Facebook profile picture is successful
  • GraphNode representing the Facebook profile picture indicates that the profile picture is the default Facebook silhouette

Expected behavior for this scenario:

  • Drupal user's profile picture field is left empty so that we will respect the possible Empty Image setting that the site builder has defined for the user picture field

Scenario 1.3 (happy flow):

  • User pictures are enabled but not required (Drupal default behavior)
  • API call for getting the Facebook profile picture is successful
  • GraphNode representing the Facebook profile picture indicates that the profile picture is NOT the default Facebook silhouette
  • File could be downloaded successfully

Expected behavior for this scenario:

  • Facebook profile picture is used as Drupal user profile picture.
  • The file is set as Drupal user's profile picture before we dispatch the event to other modules
  • The owner of the file is the newly created Drupal user.

Scenarios 2: User pictures are enabled and required (configuration where this issue started from)

Scenario 2.1:

  • User pictures are enabled and required
  • API call for getting the Facebook profile picture fails OR the profile picture download fails

Expected behavior for this scenario:

  • Log an error that the API call to read the profile picture failed / file download failed
  • Show a message to the user that new Drupal user account could not be created
  • Drupal user account is not created.

Scenario 2.2:

  • User pictures are enabled and required
  • API call for getting the Facebook profile is successful and picture was downloaded successfully

Expected behavior for this scenario:

  • Facebook profile picture is used as Drupal user profile picture even if it was the default Facebook silhouette.
  • The file is set as Drupal user's profile picture before we dispatch the event to other modules
  • The owner of the file is the newly created Drupal user.

Scenario 3: Drupal user profile does not have the standard user picture field

  • Do not try to insert the profile picture to a field which does not exist
Peter Majmesku’s picture

If somebody wishes to continue with this issue, we need to properly handle a couple of scenarios so that this could be committed.

I think your instructions are too complex.

The patch works for me. If the user has no FB image (rare cases), then there will be an error shown. This error is a bit sparse from your module right now. But I could translate it to german, so that it is more descriptive.

Any userPictureRequired() method is only overhead here.

The file will not have the owner set up correctly

That's not correct. The file belongs to user www-data and group www-data within /sites/default/files/pictures on my ubuntu linux server.

masipila’s picture

About the file ownership: I was referring to which Drupal user owns the file. I believe how you implemented the patch removes the part where the file ownership is set.

masipila’s picture

And what it comes to the other topics I listed: it's all about handling the errors properly and logging them so pretty basic stuff.

When the user_picture is NOT required, then all error situations should be handled correctly already. But when the the user picture is required and we don't have it because one of the three cases (api call failed / download failed / user didn't have a pic on Facebook), then we need to improve the error handling here.

I understand if you don't have time for this and respect that. My point was more that if someone else wants to contribute on fixing this.

Markus

masipila’s picture

Version: 8.x-3.0 » 8.x-3.x-dev
Status: Needs work » Needs review
FileSize
9.98 KB

Hi Peter,

would you have time to test if the attached patch works in the scenarios that you have had?

This patch now tries to cover the logic I was writing earlier. You were right that the logic was too complex so I simplified it a bit. Proper error handling is also included.

  • If profile pictures are enabled and required, we accept the default silhouette from Facebook.
  • If profile pictures are enabled but NOT required and the user does not have a Facebook profile picture, we do NOT download the default silhouette from Facebook. Instead we leave the Drupal user_picture field empty.
  • If profile pictures are not enabled, we don't download the picture from Facebook.

I'd really appreciate if you could test this a bit under the different scenarios before I commit this. Other members of the community are of course also more than welcome to help with testing this.

Cheers,
Markus

Peter Majmesku’s picture

Status: Needs review » Reviewed & tested by the community

Hi Markus,

I have re-viewed your patch. Thanks for your effort on this.

I have tested the patch and could register via facebook with a profile image and without a profile image. Interesting was, that there is a default profile image, which comes from facebook. See attached screenshot.

My thoughts so far from the code review:

  • You are commenting too much. Comments like in src/SimpleFbConnectFbManager.php:276 (// Something went wrong.) you can save.
  • General thing: the controller src/Controller/SimpleFbConnectController.php is doing too much. The methods are very long and scattered with if-cases and the logic is very complex. You have quite no chance to completely overview that. Properly made, there should go more into a tested service.
  • I could also run the unit tests manually. However the facebook sdk is a dependency. Only having the uninstalled module in the module folder, does not work. So there is a bit too much of dependency.

The points above are optional. I would not say, that the changes are wrong. Edit your patch, if you have time and fun on the work. Otherwise this patch is good for this community project.

One thing I would like to have: a configuration option for the return URL, after the user has been registered and the user could not been logged in, because the user needs to be activated. Right now I have modified this via a patch in my code via a hardcoded path.

Cheers!

Peter Majmesku’s picture

P.S: The return url I have created a separated feature request issue: https://www.drupal.org/node/2877476.

Peter Majmesku’s picture

FileSize
44.77 KB

Here's the screenshot from the profile image, which I have mentioned.

masipila’s picture

Hi,

I have tested the patch and could register via facebook with a profile image and without a profile image. Interesting was, that there is a default profile image, which comes from facebook.

This is by design of this new patch. When we make the API query to get the Facebook profile picture, we get as a response a GraphNode object which has the URL of the image. We also can check from this GraphNode object if the image that is indicated is the Facebook default silhouette.

As mentioned earlier:

  • If the Drupal user_picture is required, we download this silhouette so that the user creation will not fail due to missing picture.
  • If the Drupal user_picture is NOT required, then we ignore the Facebook picture if it is a silhouette. This allows the site builder to use Drupal's Default Image behavior.

    Cheers,
    Markus

masipila’s picture

Thanks also for the code review, I appreciate it. A couple of comments:

You are commenting too much.

This is probably true for some occasions. My coding style is quite verbose when it comes to documenting. The reason for this is that I want to remember the logic why I have written the logic like that when I need to get back to it.

General thing: the controller src/Controller/SimpleFbConnectController.php is doing too much. The methods are very long and scattered with if-cases and the logic is very complex. You have quite no chance to completely overview that. Properly made, there should go more into a tested service.

We have two route callbacks in the controller. One that redirects the user to Facebook for authentication and the second which responds to the route where Facebook returms the user after the user has authenticated on Facebook.

The redirect to Facebook is not complex at all in my opinion but I completely agree the method handling the return from Facebook is complex because many things can go wrong: the user may not have given the permission to his/her email address, the user may not have email address on Facebook (yes, that is possible if you've registered with phone number only) and so on. I've tried to describe with the inline comments the flow whag is going on.

It might be feasible to have this whole flow moved from the controller to a service. I'll have to think about it at some point.

I could also run the unit tests manually. However the facebook sdk is a dependency. Only having the uninstalled module in the module folder, does not work. So there is a bit too much of dependency.

There's no other way than to have the SDK as a dependency unless we would write and maintain the heavy part of this whole functionality by ourselves. That would not be feasible at all and there would for sure be some security aspects that we would overlook if we would even try.

When it comes to unit testing, it is well possible to mock the Facebook SDK classes so that we could unit test our own code. The coverage is somewhat ok for the other classes than our SimpleFbConnectFbManager (there is an open issue for this and patches are more than welcome).

Cheers,
Markus

  • masipila committed d65ad32 on 8.x-3.x
    Issue #2874179 by Peter Majmesku, masipila: User account registration...
masipila’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 8.x-3.x-dev. Thanks for your help with this!

Cheers,
Markus

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.