Repository navigation
Let a credential's owner reconnect it themselves - #2129
Merged
Merged
Conversation
Starting an OAuth connect took credentials.manage of everyone, so a Member or Viewer whose own sign-in had died could not bring it back: only an Admin could start it, and an Admin can only finish it by signing in as that person. Replacing a pasted token over the same credential already passed its owner on membership alone, so putting a sign-in right was harder than putting a token right. A connect that names a credential to re-authorize in place (ReplaceCredentialId) is now held to that credential's bar: its own person on membership, anyone else credentials.manage. A connect that names none mints a credential and keeps credentials.manage. Everything else a re-authorization checks is unchanged: the same provider account, a retired credential, an owner without standing, the rank reach over the person acted on, and the named owner being the credential's. A reconnect signs in AS the person, so it also keeps the reach over them (CredentialOwnerOrPermission.PermitsReconnect): an Admin cannot reconnect another Admin's or an Owner's sign-in, and nobody can for someone who has left the team. That was only the service's refusal, unknown to a button, so an Admin was offered a Reconnect on an Owner's sign-in that always answered 403, and a Reconnect or Replace token on the credential of someone who had left that no one could use. CallerStanding now models it, and the remedy names only the people who could do what the caller cannot. The bar is one definition, used by the pipeline (a marker and behavior), by CallerStanding for the remedy's buttons, by the credential list's new callerMayRepair, which the repository rows read, and by the OAuth callback, which asks it again of whoever started the connect before the code is exchanged: a starter demoted, removed from the team, or the person promoted past them in the ten minutes between start and callback never has a token written. The person's role is read one way, by TeamStanding.RolesActedOnAsync, which TeamMemberService now uses as well. callerMayRepair is additive: an older SPA ignores it and a newer one falls back to the role when a server sends none. No migration and no new setting. A pod from before this refuses the owner as it always did; one from after completes a connect an older pod started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /api/credentials/oauth/initnaming areplaceCredentialIdpasses the credential's own person on membership alone (a Member or Viewer whose sign-in died brings it back in place, in the starting browser and across sites through the SPA's completion page); anyone else still needscredentials.manage, and a connect that names no credential keeps its bar. The same-account rule, retired and departed refusals and the named-owner check are unchanged.callerMayRepaironGET /api/credentials, which the repository rows read, all ask the same rule over the person's role asTeamStanding.RolesActedOnAsyncreads it (TeamMemberServiceuses it too). The remedy's reasons and "who to ask" now name only people who could do what the caller cannot.callerMayRepairis an additive nullable field (an older SPA ignores it, a newer SPA falls back to the role when a server sends none); no migration, setting or change to any endpoint's request or status.Test plan
PermitsReconnecttable,CredentialPerson,CallerStandingand the remedy's wording and ordering per role, person and departed ownercallerMayRepairand the real command (accepted only if it returns) must agreeRoleHeldAsyncagrees with the resolver in a deleted team; reach agreement for every kind of personGitLabDoorkeeperStubpnpm lint,tsc --noEmit, full vitest, builddotnet build CodeSpace.sln