login method

Future<Map<String, dynamic>> login(
  1. String email,
  2. String password, {
  3. String twoFactorCode = "XXXXXX",
})

Implementation

Future<Map<String, dynamic>> login(String email, String password,
    {String twoFactorCode = "XXXXXX"}) async {
  final authInfo = await getAuthInfo(email);
  final authVersion = authInfo['authVersion'] ?? 2;
  final salt = authInfo['salt'] ?? '';

  api.log('Deriving keys...');
  final derived = await crypto.deriveKeys(password, authVersion, salt);
  final derivedPassword = derived['password']!;
  final localMasterKey = derived['masterKey']!;

  final loginPayload = {
    'email': email.toLowerCase(),
    'password': derivedPassword,
    'authVersion': authVersion,
    'twoFactorCode': twoFactorCode,
  };

  final response = await api.makeRequest(
    'POST',
    Uri.parse('${FilenApi.apiUrl}/v3/login'),
    body: json.encode(loginPayload),
    useAuth: false,
  );

  final data = json.decode(response.body);

  if (data['status'] == true && data['data'] != null) {
    final loginData = data['data'];

    List<String> rawEncryptedKeys = [];
    if (loginData['masterKeys'] is String) {
      rawEncryptedKeys = [loginData['masterKeys']];
    } else if (loginData['masterKeys'] is List) {
      rawEncryptedKeys =
          (loginData['masterKeys'] as List).map((e) => e.toString()).toList();
    }

    api.log('Decrypting ${rawEncryptedKeys.length} master keys...');

    List<String> decryptedMasterKeys = [];
    for (var encryptedKey in rawEncryptedKeys) {
      try {
        final decrypted =
            await crypto.decryptMetadata002(encryptedKey, localMasterKey);
        decryptedMasterKeys.add(decrypted);
      } catch (e) {
        api.log('Failed to decrypt a master key: $e');
      }
    }

    if (decryptedMasterKeys.isEmpty) {
      api.log('Warning: No master keys decrypted. Using local master key.');
      decryptedMasterKeys.add(localMasterKey);
    }

    return {
      'email': email,
      'apiKey': loginData['apiKey'],
      'masterKeys': decryptedMasterKeys.join('|'),
      'baseFolderUUID': loginData['baseFolderUUID'] ?? '',
      'userId': (loginData['id'] ?? loginData['userId'] ?? '').toString(),
    };
  } else {
    final code = data['code'] ?? '';
    if (code == 'enter_2fa' || code == 'wrong_2fa') throw Exception(code);
    throw Exception(data['message'] ?? 'Login failed');
  }
}