login method
Validates a GitHub authorization code and either logs in the associated user or creates a new user account if the GitHub account ID is not yet known.
This method exchanges the authorization code for an access token using
PKCE, then authenticates the user.
If a new user is created an associated UserProfile is also created.
Implementation
Future<AuthSuccess> login(
final Session session, {
required final String code,
required final String codeVerifier,
required final String redirectUri,
final Transaction? transaction,
}) async {
return await DatabaseUtil.runInTransactionOrSavepoint(
session.db,
transaction,
(final transaction) async {
final accessToken = await utils.exchangeCodeForToken(
session,
code: code,
codeVerifier: codeVerifier,
redirectUri: redirectUri,
);
final account = await utils.authenticate(
session,
accessToken: accessToken,
transaction: transaction,
);
final image = account.details.image;
if (account.newAccount) {
try {
await _userProfiles.createUserProfile(
session,
account.authUserId,
UserProfileData(
fullName: account.details.name?.trim(),
email: account.details.email,
),
transaction: transaction,
imageSource: image != null ? UserImageFromUrl(image) : null,
);
} catch (e, stackTrace) {
session.log(
'Failed to create user profile for new GitHub user.',
level: LogLevel.error,
exception: e,
stackTrace: stackTrace,
);
}
} else if (image != null) {
try {
final user = await UserProfile.db.findFirstRow(
session,
where: (final t) => t.authUserId.equals(account.authUserId),
transaction: transaction,
);
if (user != null && user.image == null) {
await _userProfiles.setUserImageFromUrl(
session,
account.authUserId,
image,
transaction: transaction,
);
}
} catch (e, stackTrace) {
session.log(
'Failed to update user profile image for existing GitHub user.',
level: LogLevel.error,
exception: e,
stackTrace: stackTrace,
);
}
}
return _tokenIssuer.issueToken(
session,
authUserId: account.authUserId,
transaction: transaction,
method: method,
scopes: account.scopes,
);
},
);
}