Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARCH-135 Add new custom DOT Application model to support OAuth2 per-application scopes. #18416

Merged
merged 1 commit into from
Jun 20, 2018

Conversation

douglashall
Copy link
Contributor

@douglashall douglashall commented Jun 20, 2018

ARCH-135

Add new custom DOT Application model to support OAuth2 per-application scopes.

This also introduces a model for persisting organization-based filters on
a per-application basis. See openedx/core/djangoapps/oauth_dispatch/docs/decisions/0007-include-organizations-in-tokens.rst
for additional details.

@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch from bb12ba3 to bf3202b Compare June 20, 2018 13:53
@douglashall douglashall changed the title Add new custom DOT Application model to support OAuth2 per-application scopes. ARCH-135 Add new custom DOT Application model to support OAuth2 per-application scopes. Jun 20, 2018
@douglashall douglashall requested review from nasthagiri and robrap June 20, 2018 14:05
@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch 2 times, most recently from 94a3008 to 8840b0e Compare June 20, 2018 15:34
@douglashall
Copy link
Contributor Author

@edx/devops Heads up! Migration coming through.

@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch from 8840b0e to f299de3 Compare June 20, 2018 16:42
]

operations = [
migrations.RunPython(migrate_application_data),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Questions about this migration:

  1. Can we pass reverse_code=RunPython.noop to be explicit that there's no rollback of this migration?
  2. What happens if the migration is run, rolled back, and then re-run? Will migrate_application_data handle that?
  3. What if migrate_application_data fails in the middle? Will re-running the migration coalesce any issues?
  4. How will we prevent or detect that no new Application entries get created in between this PR and the one that changes settings.OAUTH2_PROVIDER_APPLICATION_MODEL? Should we create another small PR that changes the value of settings.OAUTH2_PROVIDER_APPLICATION_MODEL? Should we move this migration to a management command that runs again (just in case)?

#2 and #3 are all issues that have actually happened in production, so not just theoretical.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Done.
    2+3. Switched to get_or_create instead of save.
  2. We should accept that risk. We can do a manual check after we switch to the new application model to verify that the two application tables are in sync.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@feanil FYI on this migration strategy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding:
5. The "id" field in the new and old Application models need to match exactly in order to support all previously created tokens/grants/etc. Those tables have foreign keys to the Application table via the "id" field.

scopes = ListCharField(
base_field=models.CharField(max_length=32),
size=10,
max_length=(10 * 33), # 10 * 32 character scopes, plus commas
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this number come from? From the RFC?

default=CONTENT_PROVIDER_TYPE,
)
application = models.ForeignKey(
oauth2_settings.APPLICATION_MODEL,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be dependent on the setting - or always related to ScopedApplication since they seem to be sister models? Each way has its own trade-offs, of course. I suppose the current way is more extensible, right?

What if someone changes the setting? That won't result in a new migration. But that should be Ok, I believe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this is good as is.

@@ -0,0 +1,9 @@
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: These are unused in this PR at the moment.

scopes = ListCharField(
base_field=models.CharField(max_length=32),
size=10,
max_length=(10 * 33), # 10 * 32 character scopes, plus commas
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this number come from? From the RFC?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any specification of size limits in the RFC. This was copied over from the original Microsoft PR. Did you have a different number in mind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mettursathish Is there a reason your team chose this limit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping this from 10 to 25 as discussed on Slack#architecture.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no specific reason why we chose 10.

@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch from f299de3 to 0c228be Compare June 20, 2018 17:25
@@ -46,6 +46,7 @@ django-memcached-hashring
django-method-override==0.1.0
django-model-utils==3.0.0
django-mptt>=0.8.6,<0.9
django-mysql
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this new dependency still needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm using this for the list of strings filed that stores the scopes on ScopedApplication.

@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch 3 times, most recently from 6118adc to cbfa5fd Compare June 20, 2018 18:26
@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch 4 times, most recently from 61b3b43 to a4f9f67 Compare June 20, 2018 19:35
ScopedApplication = apps.get_model('oauth_dispatch', 'ScopedApplication')

for application in Application.objects.all():
ScopedApplication.objects.get_or_create(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to use update_or_create instead?

]

operations = [
migrations.RunPython(migrate_application_data, reverse_code=migrations.RunPython.noop),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may actually want to implement a proper reverse here because if we end up making changes to the new table, we will probably want to propagate them back to the old table so auth does not break. This is an unlikely case but I'd rather have it implemented correctly if we need it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't need it. The new table will not be accessible from the app until we are certain we won't be rolling back.

@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch from a4f9f67 to bd3db55 Compare June 20, 2018 20:15
id = models.IntegerField(primary_key=True)
scopes = ListCharField(
base_field=models.CharField(max_length=32),
size=10,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to update to 25 (to be consistent with max_length.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.

…n scopes.

This also introduces a model for persisting organization-based filters on
a per-application basis. See openedx/core/djangoapps/oauth_dispatch/docs/decisions/0007-include-organizations-in-tokens.rst
for additional details.
@douglashall douglashall force-pushed the douglashall/oauth_scopes_part1 branch from bd3db55 to bab6e36 Compare June 20, 2018 20:32
@edx-status-bot
Copy link

Your PR has finished running tests. There were no failures.

@douglashall douglashall merged commit cc5f62d into master Jun 20, 2018
@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production on Thursday, June 21, 2018.

@edx-pipeline-bot
Copy link
Contributor

EdX Release Notice: This PR has been deployed to the production environment.

@edx-secure edx-secure deleted the douglashall/oauth_scopes_part1 branch January 7, 2019 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants