Skip to content

Support Feature Flag userWithId Strategy on Backend

Jason Goodman requested to merge userid-ff into master

What does this MR do?

Add backend support for the userWithId feature flag strategy.

Relevant Issue: https://gitlab.com/gitlab-org/gitlab-ee/issues/11459

Behavior of the Unleash server and ruby client in several edge cases.

1,2, 3 (with space)

The Unleash server lets you save a value like this.

Screen_Shot_2019-07-22_at_12.26.00_PM

Screen_Shot_2019-07-22_at_12.26.10_PM

It saves the value with the space in the database:

{"name":"userWithId","parameters":{"userIds":"1,2, 3"}

It also reports it with a space to clients:

        {                                                           
          "name": "userWithId",                                     
          "parameters": {                                           
            "userIds": "1,2, 3"                                     
          }                                                         
        }                                                       

But then the ruby client matches on the trimmed value. I have to make the context's user_id value 3 in order to match and have the feature enabled. 3 (with a leading space) does not match and the feature is disabled.

You can see that the ruby client trims the user id's: https://github.com/Unleash/unleash-client-ruby/blob/c88196a105d274344c26dc89bb265f98de18d71e/lib/unleash/strategy/user_with_id.rb#L16

1,2,ほげ (with unicode)

This causes no problems. The Unleash server saves the value, reports it to clients, and the ruby client will match on it.

1,2," !"#$%&'()*+-./:;<=>?@[\]^_{}~" (with special characters)

This seems to work. The Unleash server saves the value, escapes characters as necessary, returns the escaped string to clients, and the client can match on it.

Screen_Shot_2019-07-22_at_12.58.37_PM

{"name":"userWithId","parameters":{"userIds":"1,2,\" !\"#$%&'()*+-./:;<=>?@[\\]^_{}~\""}}

        {
          "name": "userWithId",
          "parameters": {
            "userIds": "1,2,\" !\"#$%&'()*+-./:;<=>?@[\\]^_{}~\""
          }
        }

1,2,,,,,,, (no values defined)

The Unleash Server saves values like this. There is a discrepancy between the UI and the values saved in the database.

Screen_Shot_2019-07-22_at_12.59.48_PM

Screen_Shot_2019-07-22_at_12.59.55_PM

Saves values in the database like:

{"name":"userWithId","parameters":{"userIds":"1,2,,,,,,,"}}

And reports them as such to clients. But this doesn't seem to cause any problems for the ruby client.

Next time I save a value, the extra blank values are removed from the database:

Screen_Shot_2019-07-22_at_1.05.16_PM

{"name":"userWithId","parameters":{"userIds":"1,2,3"}}

1,2,2,2 (duplicated)

The Unleash server will let you save values like this. The values are displayed multiple times in the UI:

Screen_Shot_2019-07-22_at_12.15.56_PM

They are saved in the database multiple times:

{"name":"userWithId","parameters":{"userIds":"hi guy spaces, and me,tab\\tcharacter,hi,hi,hi,hi"}

They are given this way to clients:

{                                                                   
  "version": 1,                                                     
  "features": [                                                                                                                         
    {                                                                                                                                   
      "name": "fog",                                                
      "description": "Turn the fog on and off",                     
      "enabled": true,                                              
      "strategies": [                                               
        {                                                           
          "name": "gradualRolloutUserId",                           
          "parameters": {                                           
            "groupId": "mygroup",                                   
            "percentage": "5"                                       
          }                                                         
        },                                                          
        {                                                           
          "name": "userWithId",                                     
          "parameters": {                                           
            "userIds": "hi guy spaces, and me,tab\\tcharacter,hi,hi,hi,hi"                                                              
          }                                                         
        }                                                           
      ],                                                            
      "variants": null,                                             
      "createdAt": "2019-06-07T18:35:23.224Z"                       
    }                                                               
  ]                                                                 
}                                                                   

The ruby client handles this situation without any issues. I can toggle the feature on locally by changing the unleash client context's user_id parameter to hi or off by setting it to something else.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... (Super long text)

I tried a string of 183 random characters. It works with Unleash. The server accepts it, saves it in the database, and returns it to clients. The client matches properly on the string. I can toggle a feature on and off for myself by setting the unleash context's user_id parameter to the long string.

You can see that it causes some trouble in the Unleash server's UI:

Screen_Shot_2019-07-22_at_12.08.08_PM

I cannot delete the long ID, because the string is too long and pushes the X beyond the clickable area.

Does this MR meet the acceptance criteria?

Conformity

Performance and testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team
Edited by Jason Goodman

Merge request reports