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

OIDC active state form #15168

Merged
merged 12 commits into from
Feb 9, 2024
Merged

Conversation

th3coop
Copy link
Contributor

@th3coop th3coop commented Jan 8, 2024

This PR follows from #13980. It adds form management portion of the ActiveState Publisher in PyPI Account settings.

Without #13980 merged, this PR have about 1400 more changed lines than it should. It'll look more like this when 13980 is merged: ActiveState#3

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch from ada3c70 to 1e9cb8b Compare January 10, 2024 00:25
@th3coop th3coop marked this pull request as ready for review January 10, 2024 18:39
@th3coop th3coop requested a review from a team as a code owner January 10, 2024 18:39
@di
Copy link
Member

di commented Jan 10, 2024

I'll review this once #13980 is merged and conflicts are resolved here!

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch 7 times, most recently from 59af76f to d4916b4 Compare January 12, 2024 15:26
@th3coop
Copy link
Contributor Author

th3coop commented Jan 12, 2024

@di, @woodruffw. Before you give this PR a super thorough review, I'll point out that I've included quite a bit of duplication tests/unit/accounts/test_views.py. I think I would be able to avoid this if I changed all of the validation tests in that file to call _add_pending_oidc_publisher and perhaps parameterize passing in the respective services values so I can check stuff like this has the right service name in the string?

That could result in quite large or complex parameterize lists though.

Any thoughts?

@di
Copy link
Member

di commented Jan 12, 2024

@th3coop We already have parametrized tests for these which were added recently, e.g. for that specific example:

@pytest.mark.parametrize(
"view_name, flag, publisher_name",
[
(
"add_pending_github_oidc_publisher",
AdminFlagValue.DISALLOW_GITHUB_OIDC,
"GitHub",
),
(
"add_pending_google_oidc_publisher",
AdminFlagValue.DISALLOW_GOOGLE_OIDC,
"Google",
),
],
)
def test_add_pending_oidc_publisher_admin_disabled(
self, monkeypatch, pyramid_request, view_name, flag, publisher_name
):
pyramid_request.user = pretend.stub()
pyramid_request.registry = pretend.stub(
settings={
"github.token": "fake-api-token",
}
)
pyramid_request.flags = pretend.stub(
disallow_oidc=pretend.call_recorder(lambda f=None: True),
)
pyramid_request.session = pretend.stub(
flash=pretend.call_recorder(lambda *a, **kw: None)
)
project_factory = pretend.stub()
project_factory_cls = pretend.call_recorder(lambda r: project_factory)
monkeypatch.setattr(views, "ProjectFactory", project_factory_cls)
pending_github_publisher_form_obj = pretend.stub()
pending_github_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_github_publisher_form_obj
)
monkeypatch.setattr(
views, "PendingGitHubPublisherForm", pending_github_publisher_form_cls
)
pending_google_publisher_form_obj = pretend.stub()
pending_google_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_google_publisher_form_obj
)
monkeypatch.setattr(
views, "PendingGooglePublisherForm", pending_google_publisher_form_cls
)
view = views.ManageAccountPublishingViews(pyramid_request)
assert getattr(view, view_name)() == {
"disabled": {
"GitHub": True,
"Google": True,
},
"pending_github_publisher_form": pending_github_publisher_form_obj,
"pending_google_publisher_form": pending_google_publisher_form_obj,
}
assert pyramid_request.flags.disallow_oidc.calls == [
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(flag),
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
]
assert pyramid_request.session.flash.calls == [
pretend.call(
(
f"{publisher_name}-based trusted publishing is temporarily "
"disabled. See https://pypi.org/help#admin-intervention for "
"details."
),
queue="error",
)
]
assert pending_github_publisher_form_cls.calls == [
pretend.call(
pyramid_request.POST,
api_token="fake-api-token",
project_factory=project_factory,
)
]

I think if you get this branch up to date, you should just be able to add a new ActiveState parameter to these existing tests, rather than duplicating them.

@th3coop
Copy link
Contributor Author

th3coop commented Jan 12, 2024

@di, i was expecting these merge conflicts to go away when #13980 was merged since I did a fresh rebase yesterday but I still see them now that that code is in main. I'll rebase again. I am now realizing that those are the params you already told me about a couple days ago.

@di
Copy link
Member

di commented Jan 12, 2024

@th3coop Is it possible you're rebasing on the out-of-date main from the Activestate fork rather than from PyPI's remote?

@th3coop
Copy link
Contributor Author

th3coop commented Jan 12, 2024

@di, that is possible. I often pull in the upstream main to my local environment though. And I was certain I had done that before doing my last series of rebases but I could easily forgotten. Sorry for the delay on this one. I really thought it was ready for review already. I'm fixing these merge conflicts right now.

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch from d4916b4 to a66fad3 Compare January 12, 2024 22:57
@th3coop
Copy link
Contributor Author

th3coop commented Jan 12, 2024

OK. @di,I got things fixed up. Again, sorry about that mixup. Also, I'm working on getting Allowing changes to a pull request branch created from a fork enabled on this PR. I don't appear to have permissions to do that.

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch 5 times, most recently from 40e20e5 to 07eb067 Compare January 12, 2024 23:38
@th3coop
Copy link
Contributor Author

th3coop commented Jan 13, 2024

Hey @di. It appears that we can't turn on **Allowing changes to a pull request branch created from a fork
**. The option to enable that doesn't show up for myself or any admins of our GitHub account and I can't find anything on the internet as to why that might be. I'm like 75% sure that it's because our fork is in the ActiveState org and not my personal GitHub account. That's my best guess based on step 4 from the docs where it says On user-owned forks.

If not having this turned on is a huge pain for y'all, let me know and I can move the remaining PRs to my personal account.

@woodruffw
Copy link
Member

Yeah, that's an unfortunate known long-standing bug with GitHub orgs and forks. The hacky workaround is to manually give the person commit rights on your fork, but that's not always desirable 🙃

@th3coop
Copy link
Contributor Author

th3coop commented Jan 13, 2024

I'm fine with that! Thanks for the workaround @woodruffw. Invites sent to yourself and DI. I'll remove you both when we get the PRs merged.

@th3coop
Copy link
Contributor Author

th3coop commented Jan 22, 2024

Thanks so much for all your time @woodruffw !

@th3coop
Copy link
Contributor Author

th3coop commented Jan 29, 2024

@miketheman will you have time to review this PR this week?

Copy link
Member

@miketheman miketheman left a comment

Choose a reason for hiding this comment

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

Thanks to the heavy lifting the other folks did before, this was relatively easy to review.

I had a few notes, questions, comments inline - the only real blocker are with the linter disables which should be an easy fix.

There's other questions and comments inline, feel free to address them as you wish.
The branch should also be rebased/merged once ready.

Comment on lines +1539 to +1541
self.metrics.increment(
"warehouse.oidc.add_publisher.ok", tags=["publisher:ActiveState"]
)
Copy link
Member

Choose a reason for hiding this comment

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

Now that we're at a third implementation, it might be smart for us to look at commonalities and refactoring opportunities. I'd invoke the Rule of Three, but I'm happy to let this become the Rule of Four, so we can see how these behave in reality.
It's also starting to feel like there's inheritance/service/Protocol opportunities here, but again, worth leaving for a real refactor.

Comment on lines +54 to +57
def _no_leading_or_trailing_dashes(form, field):
if field.data.startswith("-") or field.data.endswith("-"):
raise wtforms.validators.ValidationError(
_("Leading or trailing dashes are not allowed in the name")
)
Copy link
Member

Choose a reason for hiding this comment

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

I hear you on the specificity - it's always great to have users get the feedback that will guide them to resolution.
These validation rules are from the ActiveState service, and subject to change. Would it be smarter to have the validation here be simpler, and for the GQL API to accept the input and return the correct response in the API call?
Also not going to block on this, but something for @th3coop and the platform folks to consider.

_GRAPHQL_GET_ACTOR, {"username": actor}, process_actor_response
)

def validate_actor(self, field):
Copy link
Member

Choose a reason for hiding this comment

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

I was reading more about wtforms validators, and I think that if there's a named validator function, it fires before the validators on the field, so validate_actor() would perform API calls before the other validators like regex/dashes are in play.

It's definitely worth re-verifying - since if our validators operate in that order, then we're performing an API call regardless. I hope I'm wrong! If that is true, then it's not only this form - so I don't think it's immediately actionable, but if you can test it, that'd be great.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you like the idea here #15168 (comment). I would do that change for this validator as well. We really just need a "you entered the wrong text" kind of feedback here.

@th3coop
Copy link
Contributor Author

th3coop commented Feb 1, 2024

Thanks for the review, @miketheman! Great notes in there. I'll work through them either later today or tomorrow. The GQL API is available again if you wanted to, or have time to take it for a manual test drive. Again, sorry for that terrible timing.

Copy link
Member

@miketheman miketheman left a comment

Choose a reason for hiding this comment

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

@th3coop we're almost there! I dropped a couple of notes inline, should be straightforward changes.

Then a rebase and make translations update, and should be good to merge!

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch from d8fa465 to 8f064db Compare February 7, 2024 23:34
@th3coop th3coop force-pushed the OIDC-ActiveState-form branch from 21081d5 to 52e8231 Compare February 8, 2024 00:41
@th3coop
Copy link
Contributor Author

th3coop commented Feb 8, 2024

Alrighty @miketheman, this comment remains. I'm happy to remove the regexs for username and organization, or just leave them as is. I'm leaning towards removing them though.

Other than that though, I think we're good, assuming the checks all pa....oh they passed!

@miketheman
Copy link
Member

I'm leaning towards removing them though.

@th3coop go ahead and remove them - less is more 😁

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch from 4ff5ac6 to 9c806c9 Compare February 8, 2024 18:15
@th3coop
Copy link
Contributor Author

th3coop commented Feb 8, 2024

go ahead and remove them - less is more 😁

Agreed and done. Fixed the tests and took it for a spin and it works as I'd expect it to

Copy link
Member

@miketheman miketheman left a comment

Choose a reason for hiding this comment

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

Almost there! just a couple last bits, and rebase against main, and I think we're good to do.

@th3coop th3coop force-pushed the OIDC-ActiveState-form branch from aa679b4 to 933fefe Compare February 8, 2024 21:20
Copy link
Member

@miketheman miketheman left a comment

Choose a reason for hiding this comment

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

Yay! I'll approve now, and merge in the AM.

@miketheman miketheman merged commit 5fca44a into pypi:main Feb 9, 2024
17 checks passed
@th3coop
Copy link
Contributor Author

th3coop commented Feb 9, 2024

Yay! I'll approve now, and merge in the AM.

Hurray! Thanks so much Mike, Will and Dustin!

@miketheman
Copy link
Member

miketheman commented Feb 9, 2024

@th3coop I've gone ahead and enabled the OIDC provider on TestPYI so you can test run it over there. Missed the note at the top of #15204, disabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants