selectCustomPasswords static method

Future<void> selectCustomPasswords(
  1. Client cloudApiClient,
  2. CommandLogger logger,
  3. ProjectLaunch projectSetup
)

Implementation

static Future<void> selectCustomPasswords(
  final Client cloudApiClient,
  final CommandLogger logger,
  final ProjectLaunch projectSetup,
) async {
  const ignoredSecretNames = [
    'database',
    'emailSecretHashPepper',
    'jwtHmacSha512PrivateKey',
    'jwtRefreshTokenHashPepper',
    'serviceSecret',
    'redis',
    'mySharedPassword',
  ];

  final allPasswords = _readAllPasswords(projectSetup.projectDir);
  if (allPasswords.isEmpty) return;

  List<String> alreadySetSecretNames;
  final projectId = projectSetup.projectId;
  if (projectSetup.preexistingProject == true && projectId != null) {
    alreadySetSecretNames = await PasswordCommands.fetchPasswords(
      cloudApiClient,
      projectId: projectId,
    ).then((final passwords) => passwords.map((final p) => p.name).toList());
  } else {
    alreadySetSecretNames = [];
  }

  final filteredPasswords = allPasswords.where(
    (final p) =>
        !ignoredSecretNames.contains(p.name) &&
        !alreadySetSecretNames.contains(p.name),
  );
  if (filteredPasswords.isEmpty) return;

  final sortedPasswords = filteredPasswords.toList()
    ..sort((final a, final b) => a.section.index.compareTo(b.section.index));

  final longestPasswordNameLength = sortedPasswords
      .map((final p) => p.name.length)
      .reduce((final a, final b) => math.max(a, b));
  String padAfterName(final String name) {
    return ''.padRight(longestPasswordNameLength - name.length);
  }

  final options = sortedPasswords
      .map(
        (final p) =>
            '${p.name}: ${padAfterName(p.name)}${_hidePassword(p.value)}'
            '  (from section "${p.section.name}")',
      )
      .toList();
  final initiallySelected = options.where(
    (final s) => s.endsWith('"production")') || s.endsWith('"shared")'),
  );

  final selected = await SelectList.chooseMultiple<String>(
    prompt:
        'Custom passwords were found in config/passwords.yaml.\n'
        'You can select which of them to copy securely to Serverpod Cloud now.\n'
        '${logger.wrapStyle('Set them later with `scloud password set`.', cli.AnsiStyle.darkGray)}',
    options: options,
    initiallySelected: initiallySelected,
    terminal: logger.inlineTerminal,
    style: SelectListStyle(highlightStyle: _projectFactStyle.ansiCode),
  );
  if (selected == null) {
    logger.info('Setup cancelled.');
    throw UserAbortException();
  }

  final selectedNames = selected
      .map((final option) => option.split(':').first)
      .toSet();
  final selectedPasswords = sortedPasswords.where(
    (final p) => selectedNames.contains(p.name),
  );
  projectSetup.selectedPasswords = {
    for (final p in selectedPasswords) p.name: p.value,
  };
}