2828from warehouse .macaroons .interfaces import IMacaroonService
2929from warehouse .macaroons .services import DatabaseMacaroonService
3030from warehouse .oidc .interfaces import IOIDCPublisherService
31- from warehouse .oidc .models import PendingOIDCPublisher
31+ from warehouse .oidc .models import OIDCPublisher , PendingOIDCPublisher
3232from warehouse .oidc .services import OIDCPublisherService
3333from warehouse .packaging .interfaces import IProjectService
3434from warehouse .packaging .models import ProjectFactory
@@ -140,7 +140,9 @@ def process_oidc_request(
140140
141141 # First, try to find a pending publisher.
142142 pending_publisher = oidc_service .find_publisher (claims , pending = True )
143- if pending_publisher is not None :
143+ if pending_publisher is not None and isinstance (
144+ pending_publisher , PendingOIDCPublisher
145+ ):
144146 factory = ProjectFactory (request )
145147
146148 # If the project already exists, this pending publisher is no longer
@@ -163,7 +165,7 @@ def process_oidc_request(
163165 project_service = request .find_service (IProjectService )
164166 new_project = project_service .create_project (
165167 pending_publisher .project_name ,
166- pending_publisher .added_by ,
168+ pending_publisher .added_by_id ,
167169 request ,
168170 ratelimited = False ,
169171 )
@@ -172,7 +174,7 @@ def process_oidc_request(
172174 # Successfully converting a pending publisher into a normal publisher
173175 # is a positive signal, so we reset the associated ratelimits.
174176 ratelimiters = _ratelimiters (request )
175- ratelimiters ["user.oidc" ].clear (pending_publisher .added_by . id )
177+ ratelimiters ["user.oidc" ].clear (pending_publisher .added_by_id )
176178 ratelimiters ["ip.oidc" ].clear (request .remote_addr )
177179
178180 # There might be other pending publishers for the same project name,
@@ -199,7 +201,44 @@ def process_oidc_request(
199201 # have one and we've just converted it. Either way, look for a full publisher
200202 # to actually do the macaroon minting with.
201203 publisher = oidc_service .find_publisher (claims , pending = False )
202- if not publisher :
204+ if publisher is not None and isinstance (pending_publisher , OIDCPublisher ):
205+ # At this point, we've verified that the given JWT is valid for the given
206+ # project. All we need to do is mint a new token.
207+ # NOTE: For OIDC-minted API tokens, the Macaroon's description string
208+ # is purely an implementation detail and is not displayed to the user.
209+ macaroon_service : DatabaseMacaroonService = request .find_service (
210+ IMacaroonService , context = None
211+ )
212+ not_before = int (time .time ())
213+ expires_at = not_before + 900
214+ serialized , dm = macaroon_service .create_macaroon (
215+ request .domain ,
216+ (
217+ f"OpenID token: { str (publisher )} "
218+ f"({ datetime .fromtimestamp (not_before ).isoformat ()} )"
219+ ),
220+ [
221+ caveats .OIDCPublisher (
222+ oidc_publisher_id = str (publisher .id ),
223+ ),
224+ caveats .ProjectID (project_ids = [str (p .id ) for p in publisher .projects ]),
225+ caveats .Expiration (expires_at = expires_at , not_before = not_before ),
226+ ],
227+ oidc_publisher_id = publisher .id ,
228+ additional = {"oidc" : {"ref" : claims .get ("ref" ), "sha" : claims .get ("sha" )}},
229+ )
230+ for project in publisher .projects :
231+ project .record_event (
232+ tag = EventTag .Project .ShortLivedAPITokenAdded ,
233+ request = request ,
234+ additional = {
235+ "expires" : expires_at ,
236+ "publisher_name" : publisher .publisher_name ,
237+ "publisher_url" : publisher .publisher_url (),
238+ },
239+ )
240+ return {"success" : True , "token" : serialized }
241+ else :
203242 return _invalid (
204243 errors = [
205244 {
@@ -209,40 +248,3 @@ def process_oidc_request(
209248 ],
210249 request = request ,
211250 )
212-
213- # At this point, we've verified that the given JWT is valid for the given
214- # project. All we need to do is mint a new token.
215- # NOTE: For OIDC-minted API tokens, the Macaroon's description string
216- # is purely an implementation detail and is not displayed to the user.
217- macaroon_service : DatabaseMacaroonService = request .find_service (
218- IMacaroonService , context = None
219- )
220- not_before = int (time .time ())
221- expires_at = not_before + 900
222- serialized , dm = macaroon_service .create_macaroon (
223- request .domain ,
224- (
225- f"OpenID token: { str (publisher )} "
226- f"({ datetime .fromtimestamp (not_before ).isoformat ()} )"
227- ),
228- [
229- caveats .OIDCPublisher (
230- oidc_publisher_id = str (publisher .id ),
231- ),
232- caveats .ProjectID (project_ids = [str (p .id ) for p in publisher .projects ]),
233- caveats .Expiration (expires_at = expires_at , not_before = not_before ),
234- ],
235- oidc_publisher_id = publisher .id ,
236- additional = {"oidc" : {"ref" : claims .get ("ref" ), "sha" : claims .get ("sha" )}},
237- )
238- for project in publisher .projects :
239- project .record_event (
240- tag = EventTag .Project .ShortLivedAPITokenAdded ,
241- request = request ,
242- additional = {
243- "expires" : expires_at ,
244- "publisher_name" : publisher .publisher_name ,
245- "publisher_url" : publisher .publisher_url (),
246- },
247- )
248- return {"success" : True , "token" : serialized }
0 commit comments