@@ -335,6 +335,97 @@ void main() {
335335 expect (await cache.userSessionData (session.sessionId).get (), isNull);
336336 },
337337 );
338+
339+ testWithProfile (
340+ 'success - new email for known oauthUserId' ,
341+ testProfile: emptyTestProfile,
342+ fn: () async {
343+ final email1 = 'user@pub.dev' ;
344+ final oauthUserId1 = fakeOauthUserIdFromEmail (email1);
345+ final session1 = await accountBackend.createOrUpdateClientSession ();
346+ await accountBackend.updateClientSessionWithProfile (
347+ sessionId: session1.sessionId,
348+ profile: AuthResult (
349+ oauthUserId: oauthUserId1,
350+ email: email1,
351+ audience: activeConfiguration.pubServerAudience! ,
352+ accessToken: createFakeServiceAccountToken (
353+ email: email1,
354+ audience: activeConfiguration.pubServerAudience,
355+ ),
356+ ),
357+ );
358+ final authenticatedUser1 = await accountBackend
359+ .tryAuthenticateWebSessionUser (
360+ sessionId: session1.sessionId,
361+ hasStrictCookie: true ,
362+ csrfTokenInHeader: session1.csrfToken,
363+ requiresStrictCookie: true ,
364+ );
365+ expect (authenticatedUser1! .email, email1);
366+ final userId1 = authenticatedUser1.userId;
367+ expect (userId1, hasLength (36 ));
368+
369+ final oauthIdsBefore = await dbService
370+ .query <OAuthUserID >()
371+ .run ()
372+ .map ((u) => u.oauthUserId)
373+ .toSet ();
374+ expect (oauthIdsBefore, contains (oauthUserId1));
375+
376+ // change the email but keep the oauthUserId
377+ final newEmail = 'renamed@pub.dev' ;
378+ final session2 = await accountBackend.updateClientSessionWithProfile (
379+ sessionId: session1.sessionId,
380+ profile: AuthResult (
381+ oauthUserId: oauthUserId1,
382+ email: newEmail,
383+ audience: activeConfiguration.pubServerAudience! ,
384+ accessToken: createFakeServiceAccountToken (
385+ email: newEmail,
386+ audience: activeConfiguration.pubServerAudience,
387+ ),
388+ ),
389+ );
390+
391+ // resolves to the same user and session
392+ expect (session2.sessionId, session1.sessionId);
393+ expect (session2.userId, userId1);
394+ expect (session2.email, newEmail);
395+
396+ // User entity's email is updated in place
397+ final u = await accountBackend.lookupUserById (userId1);
398+ expect (u! .userId, userId1);
399+ expect (u.email, newEmail);
400+ expect (u.oauthUserId, oauthUserId1);
401+
402+ // new email resolves to the same user
403+ final byNewEmail = await accountBackend.lookupUserByEmail (newEmail);
404+ expect (byNewEmail.userId, userId1);
405+
406+ // the old one no longer resolves
407+ expect (await accountBackend.lookupUsersByEmail (email1), isEmpty);
408+
409+ // no new OAuthUserID mapping is created
410+ final oauthIdsAfter = await dbService
411+ .query <OAuthUserID >()
412+ .run ()
413+ .map ((u) => u.oauthUserId)
414+ .toSet ();
415+ expect (oauthIdsAfter, oauthIdsBefore);
416+
417+ // re-authenticated session is also updated
418+ final reauthenticated = await accountBackend
419+ .tryAuthenticateWebSessionUser (
420+ sessionId: session1.sessionId,
421+ hasStrictCookie: true ,
422+ csrfTokenInHeader: session1.csrfToken,
423+ requiresStrictCookie: true ,
424+ );
425+ expect (reauthenticated? .userId, userId1);
426+ expect (reauthenticated? .email, newEmail);
427+ },
428+ );
338429 });
339430 });
340431}
0 commit comments