Changes between Version 3 and Version 4 of ContribAuthImprovements


Ignore:
Timestamp:
03/22/2012 07:03:47 PM (3 years ago)
Author:
russellm
Comment:

Markup corrections

Legend:

Unmodified
Added
Removed
Modified
  • ContribAuthImprovements

    v3 v4  
    3333 * Introduce a new `USE_NEW_USER_SETTINGS` setting. This would be set as False by default in global_settings.py, and True by default in the project template. This means existing projects get a value of False, but can opt-in to True at their convenience; new projects get a value of True.
    3434 * Modify the existing User model to use this setting to determine the length/uniqueness of email and username fields
    35  * Introduce a "MigrationWarning" that will be raised if `USE_NEW_USER_SETTINGS` is False. Assuming this is introduced in 1.5, Django 1.5 users would get the warning if they have `USE_NEW_USER_SETTINGS` set to False. Django 1.6 would raise an error if `USE_NEW_USER_SETTINGS` is False. Django 1.7 would remove all references to the setting.
     35 * Introduce a "!MigrationWarning" that will be raised if `USE_NEW_USER_SETTINGS` is False. Assuming this is introduced in 1.5, Django 1.5 users would get the warning if they have `USE_NEW_USER_SETTINGS` set to False. Django 1.6 would raise an error if `USE_NEW_USER_SETTINGS` is False. Django 1.7 would remove all references to the setting.
    3636
    3737Optionally:
     
    4848 * Doesn't actually fix the problem for any use case other than "email address as username"
    4949 * Introduces a setting that immediately becomes deprecated (since it won't be needed once the migration cycle is complete)
    50  * Doesn't address the problem with any other usage of EmailField having a max_length of 75.
     50 * Doesn't address the problem with any other usage of !EmailField having a max_length of 75.
    5151 * Introduces a circular dependency between settings and models. When settings are loaded, `INSTALLED_APPS` is inspected, and each models file is loaded. If a models file contains a reference to settings, hilarity can ensue. This isn't a problem *most* of the time, but it can lead to some interesting side effects.
    5252
    5353== Solution 1a: Superminimal with forced migration ==
    5454
    55 As for Solution 1, but don't have the setting -- *require* the database migration as part of the 1.5 upgrade path.
     55As for Solution 1, but don't have the setting -- ''require'' the database migration as part of the 1.5 upgrade path.
    5656
    5757=== Advantages ===
     
    6464
    6565 * Is a huge backwards incompatibility: Requires that every Django user upgrading read, understand, and act upon the instructions in the release notes.
    66  * Poor failure modes. If a users fail to read and act on the instructions in the release notes, their projects won't fail until the first user enters an email that is longer than 75 characters, or a username longer than 30 characters, at which point DatabaseErrors will be raised.
     66 * Poor failure modes. If a users fail to read and act on the instructions in the release notes, their projects won't fail until the first user enters an email that is longer than 75 characters, or a username longer than 30 characters, at which point !DatabaseErrors will be raised.
    6767 
    6868== Solution 2: `AUTH_USER_MODEL` setting ==
     
    9898
    9999 * Has the same settings-models circular dependency problem as Solution 1.
    100  * Doesn't address the !EmailField length problem for existing users. We could address this by having a User model (reflecting current field lengths) and a new SimpleUser (that reflects better defaults); then use global_settings and project template settings to define which User is the default for new vs existing projects.
     100 * Doesn't address the !EmailField length problem for existing users. We could address this by having a User model (reflecting current field lengths) and a new !SimpleUser (that reflects better defaults); then use global_settings and project template settings to define which User is the default for new vs existing projects.
    101101 * Doesn't solve the analogous problem for any other project. E.g., contrib.comments already has pluggable Comments models, and has invented a bespoke solution. Other projects will have similar needs; this solution doesn't address the duplication of code.
    102102 * Has unpredictable failure modes if a third-party app assumes that User has a certain attribute or property which the project-provided User model doesn't support (or supports in a way different to the core auth.User model).
     
    125125=== Problems ===
    126126
    127  * No transparent update path -- requires that third party apps be updated to be "pluggable auth compatible". This means app authors need to convert all ForeignKey(User) into LazyForeignKey('auth.User'), and modify any usage of forms etc. This could be considered a benefit, however; Migrating User models is a nontrivial step, and it should probably involve some opt-in engineering.
    128 
    129  * Doesn't address the immediate problem for EmailField. We could do the same User/!SimpleUser conversion here; with the added benefit that we are also introducing App Refactor, so we can use the distinction between an "unconfigured" auth app and a "Django 1.5 App Refactor Configured" auth app as the point for identifying whether User or SimpleUser is in use.
     127 * No transparent update path -- requires that third party apps be updated to be "pluggable auth compatible". This means app authors need to convert all !ForeignKey(User) into !LazyForeignKey('auth.User'), and modify any usage of forms etc. This could be considered a benefit, however; Migrating User models is a nontrivial step, and it should probably involve some opt-in engineering.
     128
     129 * Doesn't address the immediate problem for !EmailField. We could do the same User/!SimpleUser conversion here; with the added benefit that we are also introducing App Refactor, so we can use the distinction between an "unconfigured" auth app and a "Django 1.5 App Refactor Configured" auth app as the point for identifying whether User or !SimpleUser is in use.
    130130
    131131== Solution 3a: Transparent !LazyForeignKeys ==
     
    135135=== Advantages ===
    136136
    137  * As for Solution 3, but provides a transparent migration path for apps -- no need to manually change ForeignKey(User). However, depending on your perspective, this might not actually be an advantage at all, because it removes the opt-in migration path.
     137 * As for Solution 3, but provides a transparent migration path for apps -- no need to manually change !ForeignKey(User). However, depending on your perspective, this might not actually be an advantage at all, because it removes the opt-in migration path.
    138138
    139139=== Problems ===
     
    180180contrib.admin requires a permissions API on User. However, this API isn't an obvious thing to require for *all* User objects. There has been very little discussion about the possibility of an abstract API for permissions.
    181181
    182 The best approach here may be implement contrib.admin's permissions API as a mixin, separate to the AbstractUser base class. This would allow someone who doesn't want admin's permission model to avoid them, while making it easy to include all Django's permission requirements if the developer wants to use contrib.admin.
     182The best approach here may be implement contrib.admin's permissions API as a mixin, separate to the !AbstractUser base class. This would allow someone who doesn't want admin's permission model to avoid them, while making it easy to include all Django's permission requirements if the developer wants to use contrib.admin.
    183183
    184184=== Forms ===
    185185
    186 If an app creates a form (or ModelForm) on User, the exact contents of that form will be unpredictable. It will be extremely easy to define a form in an app that has clean methods or widget overrides that reference fields that don't exist on the User model in use.
    187 
    188 It may be necessary to prevent ModelForm from being used on User (or any other pluggable model in the App Refactor case), and encourage app developers to make any Forms that they have configurable. This is analogous to Django's existing configurability for LoginForm et al.
     186If an app creates a form (or !ModelForm) on User, the exact contents of that form will be unpredictable. It will be extremely easy to define a form in an app that has clean methods or widget overrides that reference fields that don't exist on the User model in use.
     187
     188It may be necessary to prevent !ModelForm from being used on User (or any other pluggable model in the App Refactor case), and encourage app developers to make any Forms that they have configurable. This is analogous to Django's existing configurability for !LoginForm et al.
    189189
    190190=== Inheritance ===
     
    196196== Parallel concerns ==
    197197
    198 None of these fully address the limitations with EmailField -- that the default max_length of 75 is too short to hold all email addresses. As a separate concern, we could address this problem in the same way that Solution 1 proposes to fix the User model, but focussed on the EmailField's max_length argument specifically:
     198None of these fully address the limitations with !EmailField -- that the default max_length of 75 is too short to hold all email addresses. As a separate concern, we could address this problem in the same way that Solution 1 proposes to fix the User model, but focussed on the !EmailField's max_length argument specifically:
    199199
    200200 * Introduce a new `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` setting. This would be set as False by default in global_settings.py, and True by default in the project template. This means existing projects get a value of False, but can opt-in to True at their convenience; new projects get a value of True.
    201  * Modify the EmailField definition to use this setting to determine the max_length
    202  * Introduce a "MigrationWarning" that will be raised if `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` is False (or max_length isn't manually specified). Assuming this is introduced in 1.5, Django 1.5 users would get the warning if they have `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` set to False. Django 1.6 would raise an error if `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` is False. Django 1.7 would remove all reference to the setting.
    203 
    204 This would address the problem for ''all'' EmailFields, not just the one in auth.User. This fix could be used in conjunction with any of the solutions proposed here; in fact, it would make some of them simpler (since there wouldn't be a need for a SimpleUser to migrate to an improved email field length).
     201 * Modify the !EmailField definition to use this setting to determine the max_length
     202 * Introduce a "!MigrationWarning" that will be raised if `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` is False (or max_length isn't manually specified). Assuming this is introduced in 1.5, Django 1.5 users would get the warning if they have `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` set to False. Django 1.6 would raise an error if `ALLOW_RFC_COMPLIANT_EMAIL_ADDRESSES` is False. Django 1.7 would remove all reference to the setting.
     203
     204This would address the problem for ''all'' !EmailFields, not just the one in auth.User. This fix could be used in conjunction with any of the solutions proposed here; in fact, it would make some of them simpler (since there wouldn't be a need for a !SimpleUser to migrate to an improved email field length).
    205205
    206206== Recommendations ==
Back to Top