From d8b90849f3090a9d5be94d2beadae0b2d8e225e9 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Mon, 3 Jul 2023 12:53:41 -0400 Subject: [PATCH] Proper firebase admin service account access --- .gitignore | 1 + lib/firebase/score.dart | 9 +- lib/firebase/score_calculator.dart | 12 +- lib/firebase/scores.dart | 49 ++++++- lib/game/components/count_down.dart | 2 +- lib/leaderboard/view/leaderboard_page.dart | 7 +- pubspec.lock | 146 ++++++++++++++++++++- pubspec.yaml | 2 + 8 files changed, 211 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 24476c5..5edfcbb 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release +.secrets diff --git a/lib/firebase/score.dart b/lib/firebase/score.dart index 72887f5..b780e68 100644 --- a/lib/firebase/score.dart +++ b/lib/firebase/score.dart @@ -2,19 +2,22 @@ import 'package:firedart/firestore/models.dart'; class Score { final int playerId; - final String email; + final String username; final int score; Score({ required this.playerId, - required this.email, + required this.username, required this.score, }); Score.fromDocument(Document document) : this( playerId: document.map['playerId'] as int, - email: document.map['email'] as String, + username: document.map['username'] as String, score: document.map['score'] as int, ); + + @override + String toString() => '[$playerId] $username: $score'; } diff --git a/lib/firebase/score_calculator.dart b/lib/firebase/score_calculator.dart index 84e458a..70f97b7 100644 --- a/lib/firebase/score_calculator.dart +++ b/lib/firebase/score_calculator.dart @@ -6,6 +6,9 @@ class _PlayerScore { int score = 0; _PlayerScore(this.player); + + @override + String toString() => '$player: $score'; } class ScoreCalculator { @@ -15,13 +18,14 @@ class ScoreCalculator { final scores = points.entries .toList() .sortedBy((entry) => entry.value) - .map((entry) => _PlayerScore(entry.key)); + .map((entry) => _PlayerScore(entry.key)) + .toList(); final numPlayers = points.length; final totalScore = points.values.reduce((a, b) => a + b); var jackpot = numPlayers; - if (jackpot == 0) { + if (jackpot == 0 || totalScore == 0) { return {}; } @@ -39,9 +43,7 @@ class ScoreCalculator { } return Map.fromEntries( - scores - .map((score) => MapEntry(score.player, score.score)) - .where((element) => element.value > 0), + scores.where((e) => e.score > 0).map((e) => MapEntry(e.player, e.score)), ); } } diff --git a/lib/firebase/scores.dart b/lib/firebase/scores.dart index c662dba..28d7d88 100644 --- a/lib/firebase/scores.dart +++ b/lib/firebase/scores.dart @@ -1,34 +1,73 @@ +import 'dart:io'; + +import 'package:firebase_admin/firebase_admin.dart'; import 'package:firedart/firedart.dart'; +import 'package:firedart/firestore/token_authenticator.dart'; import 'package:lightrunners/firebase/score.dart'; +import 'package:uuid/uuid.dart'; class Scores { - static late Firestore firestore; + static const uuid = Uuid(); + static Firestore? _firestore; Scores._(); + static Future _createCustomToken() => FirebaseAdmin.instance + .initializeApp( + AppOptions( + credential: FirebaseAdmin.instance + .certFromPath('.secrets/lightrunners-service-account.json'), + ), + ) + .auth() + .createCustomToken(uuid.v4()); + static Future init() async { - // NOTE: This will not work. support was removed from the library const projectId = 'lightrunners-e89a9'; - Firestore.initialize(projectId); - firestore = Firestore.instance; + final apiKey = File('.secrets/api-key.conf').readAsStringSync(); + + final customToken = await _createCustomToken(); + + final tokenStore = VolatileStore(); + + final auth = FirebaseAuth(apiKey, tokenStore); + await auth.signInWithCustomToken(customToken); + + final authenticator = TokenAuthenticator.from(auth)?.authenticate; + _firestore = Firestore(projectId, authenticator: authenticator); } static Future> topScores() async { + final firestore = _firestore; + if (firestore == null) { + print('Error: Firestore not initialized.'); + return []; + } + final page = await firestore .collection('scores') .orderBy('score', descending: true) .limit(10) .get(); - return page.map(Score.fromDocument).toList(); + final results = page.map(Score.fromDocument).toList(); + print('Fetch top scores: $results'); + return results; } static Future updateScore({ required int playerId, required int score, }) async { + final firestore = _firestore; + if (firestore == null) { + print('Error: Firestore not initialized.'); + return; + } + final document = firestore.collection('scores').document(playerId.toString()); if (await document.exists) { + print('Updating score for player id $playerId to $score.'); await document.update({'score': score}); } else { print('Error: Score not found for player id $playerId.'); diff --git a/lib/game/components/count_down.dart b/lib/game/components/count_down.dart index c0fbe58..3685616 100644 --- a/lib/game/components/count_down.dart +++ b/lib/game/components/count_down.dart @@ -4,7 +4,7 @@ import 'package:flutter/painting.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:lightrunners/ui/ui.dart'; -const _matchLength = 60.0; +const _matchLength = 20.0; const _radius = Radius.circular(3.0); class CountDown extends PositionComponent { diff --git a/lib/leaderboard/view/leaderboard_page.dart b/lib/leaderboard/view/leaderboard_page.dart index c1d99a6..ed59ca5 100644 --- a/lib/leaderboard/view/leaderboard_page.dart +++ b/lib/leaderboard/view/leaderboard_page.dart @@ -122,9 +122,12 @@ class _LeaderboardPageState extends State { } String _toScoreboardLine(Score record) { - final name = record.email.substring( + final name = record.username.substring( 0, - min(record.email.length, _maxCharactersScoreBoard - _maxScoreDigits - 1), + min( + record.username.length, + _maxCharactersScoreBoard - _maxScoreDigits - 1, + ), ); final maxScore = pow(10, _maxScoreDigits) - 1; final score = record.score diff --git a/pubspec.lock b/pubspec.lock index f694c90..f4762ae 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _discoveryapis_commons: + dependency: transitive + description: + name: _discoveryapis_commons + sha256: f8bb1fdbd77f3d5c1d62b5b0eca75fbf1e41bf4f6c62628f880582e2182ae45d + url: "https://pub.dev" + source: hosted + version: "1.0.6" _fe_analyzer_shared: dependency: transitive description: @@ -33,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: b74e3842a52c61f8819a1ec8444b4de5419b41a7465e69d4aa681445377398b0 + url: "https://pub.dev" + source: hosted + version: "1.4.1" async: dependency: transitive description: @@ -153,6 +169,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + crypto_keys: + dependency: transitive + description: + name: crypto_keys + sha256: acc19abf34623d990a0e8aec69463d74a824c31f137128f42e2810befc509ad0 + url: "https://pub.dev" + source: hosted + version: "0.3.0+1" + dotenv: + dependency: transitive + description: + name: dotenv + sha256: e169b516bc7b88801919e1c508772bcb8e3d0d1776a43f74ab692c57e741cd8a + url: "https://pub.dev" + source: hosted + version: "4.1.0" + expressions: + dependency: transitive + description: + name: expressions + sha256: "75ca4343f9f8a38087bea130cf51395d737d87c6947cc19cbb8fb2732cae1a27" + url: "https://pub.dev" + source: hosted + version: "0.2.5" fake_async: dependency: transitive description: @@ -177,6 +217,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" + firebase_admin: + dependency: "direct main" + description: + name: firebase_admin + sha256: "6c33155e2b1b072d47b5297504361ee5d2fa89998598574fa0ea891f7d7244b4" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + firebase_dart: + dependency: transitive + description: + name: firebase_dart + sha256: "705a4b3f19402d9e4b61ec93bb3b8e0ef80f77b1d84331a774e651c874f97a2f" + url: "https://pub.dev" + source: hosted + version: "1.0.11" firedart: dependency: "direct main" description: @@ -306,6 +362,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.1" + gcloud: + dependency: transitive + description: + name: gcloud + sha256: "64e1f3b8e94d3ad0477fd25daf17ed5fb8590f1cda293bfd2616243a8da3c22f" + url: "https://pub.dev" + source: hosted + version: "0.8.9" glob: dependency: transitive description: @@ -322,6 +386,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.4" + googleapis: + dependency: transitive + description: + name: googleapis + sha256: dfea9984f0785ed445ba78e2aa8c55dadd86d6a60ea9e0ffbadad51edb5e7e36 + url: "https://pub.dev" + source: hosted + version: "9.2.0" googleapis_auth: dependency: transitive description: @@ -338,6 +410,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.2" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" http: dependency: transitive description: @@ -375,6 +455,14 @@ packages: description: flutter source: sdk version: "0.0.0" + intl: + dependency: transitive + description: + name: intl + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" + source: hosted + version: "0.17.0" io: dependency: transitive description: @@ -383,6 +471,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + jose: + dependency: transitive + description: + name: jose + sha256: "06d28181b3ca26ffb83bf943f62f29d6b1b55793c852a389d3a29e6a5f54d325" + url: "https://pub.dev" + source: hosted + version: "0.3.3" js: dependency: transitive description: @@ -439,6 +535,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + openid_client: + dependency: transitive + description: + name: openid_client + sha256: "514c0ba645b81029c28999831a70cb055dda1a3bc60be759a04d2556f60ec960" + url: "https://pub.dev" + source: hosted + version: "0.4.7" ordered_set: dependency: transitive description: @@ -511,6 +615,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" phased: dependency: "direct main" description: @@ -575,6 +687,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" shelf: dependency: transitive description: @@ -612,6 +740,14 @@ packages: description: flutter source: sdk version: "0.0.99" + sortedmap: + dependency: transitive + description: + name: sortedmap + sha256: "8c9e19b93c7e1b4d795776a02719df229606cb57f46f857a7f6eb80c97fc0600" + url: "https://pub.dev" + source: hosted + version: "0.5.3" source_map_stack_trace: dependency: transitive description: @@ -717,7 +853,7 @@ packages: source: hosted version: "1.3.1" uuid: - dependency: transitive + dependency: "direct main" description: name: uuid sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" @@ -780,6 +916,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.3" + x509: + dependency: transitive + description: + name: x509 + sha256: "6db77b0baecf54584f886607247e9dedd9fd63f1e2d0ee0a00b5bb353fd7885f" + url: "https://pub.dev" + source: hosted + version: "0.2.3" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b116fc7..e61ef11 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,6 +9,7 @@ environment: dependencies: collection: ^1.17.0 + firebase_admin: ^0.2.0 firedart: ^0.9.5 flame: ^1.8.0 flame_audio: ^2.0.3 @@ -18,6 +19,7 @@ dependencies: gamepads: ^0.1.1 google_fonts: ^4.0.4 phased: ^0.0.3 + uuid: ^3.0.7 vector_math: ^2.1.4 dev_dependencies: