fetchAccountDetails method

Future<GitHubAccountDetails> fetchAccountDetails(
  1. Session session, {
  2. required String accessToken,
})

Returns the account details for the given accessToken.

This method calls GitHub's user API.

Throws GitHubAccessTokenVerificationException if the user info retrieval fails.

Implementation

Future<GitHubAccountDetails> fetchAccountDetails(
  final Session session, {
  required final String accessToken,
}) async {
  // More info on the user API:
  // https://docs.github.com/en/rest/users/users#get-the-authenticated-user
  final response = await http.get(
    Uri.https('api.github.com', '/user'),
    headers: {
      'Authorization': 'Bearer $accessToken',
      'Accept': 'application/vnd.github+json',
      'X-GitHub-Api-Version': '2022-11-28',
    },
  );

  if (response.statusCode != 200) {
    session.logAndThrow(
      'Failed to verify access token from GitHub: ${response.statusCode}',
    );
  }

  Map<String, dynamic> data;
  try {
    data = jsonDecode(response.body) as Map<String, dynamic>;
  } catch (e) {
    session.logAndThrow('Invalid user info from GitHub: $e');
  }

  if (data['email'] == null) {
    final emailResponse = await http.get(
      Uri.https('api.github.com', '/user/emails'),
      headers: {
        'Authorization': 'Bearer $accessToken',
        'Accept': 'application/vnd.github+json',
        'X-GitHub-Api-Version': '2022-11-28',
      },
    );
    if (emailResponse.statusCode == 200) {
      try {
        final emails = (jsonDecode(emailResponse.body) as List)
            .cast<Map<String, dynamic>>();
        final primary = emails.firstWhere(
          (final e) => e['primary'] == true && e['verified'] == true,
          orElse: () => <String, dynamic>{},
        );
        if (primary['email'] is String) {
          data['email'] = primary['email'];
        }
      } catch (e) {
        session.log(
          'Failed to fetch primary email from GitHub: $e',
          level: LogLevel.debug,
          exception: e,
        );
      }
    }
  }

  GitHubAccountDetails details;
  try {
    details = _parseAccountDetails(data);
  } catch (e) {
    session.logAndThrow('Invalid user info from GitHub: $e');
  }

  return details;
}