Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSG-5810 #95

Merged
merged 12 commits into from
Jan 24, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ internal class PassageFlutter(private val activity: Activity, appId: String) {

fun newRegisterOneTimePasscode(call: MethodCall, result: MethodChannel.Result) {
val identifier = call.argument<String>("identifier") ?: return invalidArgumentError(result)
val language = call.argument<String?>("language")
CoroutineScope(Dispatchers.IO).launch {
try {
val otpId = passage.oneTimePasscode.register(identifier).otpId
val otpId = passage.oneTimePasscode.register(identifier, language).otpId
result.success(otpId)
} catch (e: Exception) {
result.error(PassageFlutterError.OTP_ERROR.name, e.message, e.toString())
Expand All @@ -115,9 +116,10 @@ internal class PassageFlutter(private val activity: Activity, appId: String) {

fun newLoginOneTimePasscode(call: MethodCall, result: MethodChannel.Result) {
val identifier = call.argument<String>("identifier") ?: return invalidArgumentError(result)
val language = call.argument<String?>("language")
CoroutineScope(Dispatchers.IO).launch {
try {
val otpId = passage.oneTimePasscode.login(identifier).otpId
val otpId = passage.oneTimePasscode.login(identifier, language).otpId
result.success(otpId)
} catch (e: Exception) {
result.error(PassageFlutterError.OTP_ERROR.name, e.message, e.toString())
Expand Down Expand Up @@ -151,9 +153,10 @@ internal class PassageFlutter(private val activity: Activity, appId: String) {

fun newRegisterMagicLink(call: MethodCall, result: MethodChannel.Result) {
val identifier = call.argument<String>("identifier") ?: return invalidArgumentError(result)
val language = call.argument<String?>("language")
CoroutineScope(Dispatchers.IO).launch {
try {
val magicLinkId = passage.magicLink.register(identifier).id
val magicLinkId = passage.magicLink.register(identifier, language).id
result.success(magicLinkId)
} catch (e: Exception) {
result.error(PassageFlutterError.MAGIC_LINK_ERROR.name, e.message, e.toString())
Expand All @@ -163,9 +166,10 @@ internal class PassageFlutter(private val activity: Activity, appId: String) {

fun newLoginMagicLink(call: MethodCall, result: MethodChannel.Result) {
val identifier = call.argument<String>("identifier") ?: return invalidArgumentError(result)
val language = call.argument<String?>("language")
CoroutineScope(Dispatchers.IO).launch {
try {
val magicLinkId = passage.magicLink.login(identifier).id
val magicLinkId = passage.magicLink.login(identifier, language).id
result.success(magicLinkId)
} catch (e: Exception) {
result.error(PassageFlutterError.MAGIC_LINK_ERROR.name, e.message, e.toString())
Expand Down Expand Up @@ -419,12 +423,13 @@ internal class PassageFlutter(private val activity: Activity, appId: String) {

fun changeEmail(call: MethodCall, result: MethodChannel.Result) {
val newEmail = call.argument<String>("newEmail") ?: return invalidArgumentError(result)
val language = call.argument<String?>("language")
CoroutineScope(Dispatchers.IO).launch {
try {
val user = passage.currentUser.userInfo() ?: throw PassageUserUnauthorizedException(
"User is not authorized."
)
val magicLinkId = passage.currentUser.changeEmail(newEmail)?.id
val magicLinkId = passage.currentUser.changeEmail(newEmail, language)?.id
result.success(magicLinkId)
} catch (e: Exception) {
val error = when (e) {
Expand All @@ -441,10 +446,11 @@ internal class PassageFlutter(private val activity: Activity, appId: String) {

fun changePhone(call: MethodCall, result: MethodChannel.Result) {
val newPhone = call.argument<String>("newPhone") ?: return invalidArgumentError(result)
val language = call.argument<String?>("language")
CoroutineScope(Dispatchers.IO).launch {
try {
val user = passage.currentUser.userInfo()
val magicLinkId = passage.currentUser.changePhone(newPhone)?.id
val magicLinkId = passage.currentUser.changePhone(newPhone, language)?.id
result.success(magicLinkId)
} catch (e: Exception) {
val error = when (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void main() {
await loginWithMagicLink();
final date = DateTime.now().millisecondsSinceEpoch;
final identifier = '[email protected]';
final response = await passage.currentUser.changeEmail(identifier);
final response = await passage.currentUser.changeEmail(identifier, language: "es");
expect(response, isNotNull);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
Expand Down
2 changes: 1 addition & 1 deletion integrationtestapp/integration_test/magic_link_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void main() {
test('testActivateLoginMagicLink', () async {
try {
await passage.magiclink.login(
IntegrationTestConfig.existingUserEmailMagicLink);
IntegrationTestConfig.existingUserEmailMagicLink, language:"es");
await Future.delayed(const Duration(
milliseconds: IntegrationTestConfig.waitTimeMilliseconds));
final magicLinkStr = await MailosaurAPIClient.getMostRecentMagicLink();
Expand Down
2 changes: 1 addition & 1 deletion integrationtestapp/integration_test/otp_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void main() {
final identifier =
"authentigator+$date@${MailosaurAPIClient.serverId}.mailosaur.net";
try {
final oneTimePasscode = (await passage.oneTimePasscode.register(identifier));
final oneTimePasscode = (await passage.oneTimePasscode.register(identifier, language: 'es'));
await Future.delayed(const Duration(
milliseconds: IntegrationTestConfig.waitTimeMilliseconds));
final otp = await MailosaurAPIClient.getMostRecentOneTimePasscode();
Expand Down
6 changes: 3 additions & 3 deletions integrationtestapp/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PODS:
- Flutter (1.0.0)
- integration_test (0.0.1):
- Flutter
- passage_flutter (1.0.0):
- passage_flutter (1.1.1):
- Flutter
- PassageSwift (= 1.0.2)
- PassageSwift (1.0.2):
Expand All @@ -30,8 +30,8 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
AnyCodable-FlightSchool: 9d48ed579c898378e189bb0a89faebf9eb8a46a7
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4
passage_flutter: 60c06e8730750f0516d86fc14c4fb25087b827db
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
passage_flutter: 46098def9413ab67515fd61d485a878ea1550dda
PassageSwift: 0874d7abdd8e57e92c1ae6ead0d59c6024f8867b

PODFILE CHECKSUM: 6a26cacf19c7fcde87d9c59e8f24986138e82f3b
Expand Down
2 changes: 1 addition & 1 deletion integrationtestapp/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.1.0"
version: "1.1.1"
path:
dependency: transitive
description:
Expand Down
22 changes: 14 additions & 8 deletions ios/Classes/PassageFlutter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ internal class PassageFlutter {
result(error)
return
}
let language = (arguments as? [String: Any])?["language"] as? String
Task {
do {
let otp = try await passage.oneTimePasscode.register(identifier: identifier)
let otp = try await passage.oneTimePasscode.register(identifier: identifier, language: language)
result(otp.otpId)
} catch {
let error = FlutterError(
Expand All @@ -106,9 +107,10 @@ internal class PassageFlutter {
result(error)
return
}
let language = (arguments as? [String: Any])?["language"] as? String
Task {
do {
let otp = try await passage.oneTimePasscode.login(identifier: identifier)
let otp = try await passage.oneTimePasscode.login(identifier: identifier, language: language)
result(otp.otpId)
} catch {
let error = FlutterError(
Expand Down Expand Up @@ -154,9 +156,10 @@ internal class PassageFlutter {
result(error)
return
}
let language = (arguments as? [String: Any])?["language"] as? String
Task {
do {
let ml = try await passage.magicLink.register(identifier: identifier)
let ml = try await passage.magicLink.register(identifier: identifier, language: language)
result(ml.id)
} catch {
let error = FlutterError(
Expand All @@ -175,9 +178,10 @@ internal class PassageFlutter {
result(error)
return
}
let language = (arguments as? [String: Any])?["language"] as? String
Task {
do {
let ml = try await passage.magicLink.login(identifier: identifier)
let ml = try await passage.magicLink.login(identifier: identifier, language: language)
result(ml.id)
} catch {
let error = FlutterError(
Expand Down Expand Up @@ -421,14 +425,15 @@ internal class PassageFlutter {
}

internal func changeEmail(arguments: Any?, result: @escaping FlutterResult) {
guard let newEmail = (arguments as? [String: String])?["newEmail"] else {
guard let newEmail = (arguments as? [String: Any])?["newEmail"] as? String else {
let error = PassageFlutterError.INVALID_ARGUMENT.defaultFlutterError
result(error)
return
}
let language = (arguments as? [String: Any])?["language"] as? String
Task {
do {
let magicLink = try await passage.currentUser.changeEmail(newEmail: newEmail)
let magicLink = try await passage.currentUser.changeEmail(newEmail: newEmail, language: language)
result(magicLink.id)
} catch let error as CurrentUserError {
result(handleCurrentUserError(error))
Expand All @@ -444,14 +449,15 @@ internal class PassageFlutter {
}

internal func changePhone(arguments: Any?, result: @escaping FlutterResult) {
guard let newPhone = (arguments as? [String: String])?["newPhone"] else {
guard let newPhone = (arguments as? [String: Any])?["newPhone"] as? String else {
let error = PassageFlutterError.INVALID_ARGUMENT.defaultFlutterError
result(error)
return
}
let language = (arguments as? [String: Any])?["language"] as? String
Task {
do {
let magicLink = try await passage.currentUser.changePhone(newPhone: newPhone)
let magicLink = try await passage.currentUser.changePhone(newPhone: newPhone, language: language)
result(magicLink.id)
} catch let error as CurrentUserError {
result(handleCurrentUserError(error))
Expand Down
6 changes: 4 additions & 2 deletions lib/passage_current_user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,31 @@ class PassageCurrentUser {
///
/// Parameters:
/// - `newEmail`: The user's new email.
/// - `language`: The language code for the email change.
///
/// Returns:
/// A `Future<MagicLink>` representing the magic link
///
/// Throws:
/// `PassageError`
Future<MagicLink> changeEmail(String newEmail, {String? language}) {
return PassageFlutterPlatform.instance.changeEmail(newEmail);
return PassageFlutterPlatform.instance.changeEmail(newEmail, language);
}

/// Initiates a phone number change for the authenticated user. A phone change requires verification,
/// so an email will be sent to the user which they must verify before the phone change takes effect.
///
/// Parameters:
/// - `newPhone`: The user's new phone number.
/// - The language code for the phone change.
///
/// Returns:
/// A `Future<MagicLink>` representing the magic link
///
/// Throws:
/// `PassageError`
Future<MagicLink> changePhone(String newPhone, {String? language}) {
return PassageFlutterPlatform.instance.changePhone(newPhone);
return PassageFlutterPlatform.instance.changePhone(newPhone, language);
}

/// Attempts to create and register a new passkey for the authenticated user.
Expand Down
24 changes: 12 additions & 12 deletions lib/passage_flutter_platform/passage_flutter_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,21 @@ class MethodChannelPassageFlutter extends PassageFlutterPlatform {
// OTP METHODS

@override
Future<String> newRegisterOneTimePasscode(String identifier) async {
Future<String> newRegisterOneTimePasscode(String identifier, String? language) async {
try {
final result = await methodChannel.invokeMethod<String>(
'newRegisterOneTimePasscode', {'identifier': identifier});
'newRegisterOneTimePasscode', {'identifier': identifier, 'language': language});
return result!;
} catch (e) {
throw PassageError.fromObject(object: e);
}
}

@override
Future<String> newLoginOneTimePasscode(String identifier) async {
Future<String> newLoginOneTimePasscode(String identifier, String? language) async {
try {
final result = await methodChannel.invokeMethod<String>(
'newLoginOneTimePasscode', {'identifier': identifier});
'newLoginOneTimePasscode', {'identifier': identifier, 'language': language});
return result!;
} catch (e) {
throw PassageError.fromObject(object: e);
Expand All @@ -98,21 +98,21 @@ class MethodChannelPassageFlutter extends PassageFlutterPlatform {
// MAGIC LINK METHODS

@override
Future<String> newRegisterMagicLink(String identifier) async {
Future<String> newRegisterMagicLink(String identifier, String? language) async {
try {
final result = await methodChannel.invokeMethod<String>(
'newRegisterMagicLink', {'identifier': identifier});
'newRegisterMagicLink', {'identifier': identifier, 'language': language});
return result!;
} catch (e) {
throw PassageError.fromObject(object: e);
}
}

@override
Future<String> newLoginMagicLink(String identifier) async {
Future<String> newLoginMagicLink(String identifier, String? language) async {
try {
final result = await methodChannel.invokeMethod<String>(
'newLoginMagicLink', {'identifier': identifier});
'newLoginMagicLink', {'identifier': identifier, 'language': language});
return result!;
} catch (e) {
throw PassageError.fromObject(object: e);
Expand Down Expand Up @@ -316,21 +316,21 @@ class MethodChannelPassageFlutter extends PassageFlutterPlatform {
}

@override
Future<MagicLink> changeEmail(String newEmail) async {
Future<MagicLink> changeEmail(String newEmail, String? language) async {
try {
final magicLinkId = await methodChannel
.invokeMethod<String>('changeEmail', {'newEmail': newEmail});
.invokeMethod<String>('changeEmail', {'newEmail': newEmail, 'language': language});
return MagicLink(magicLinkId!);
} catch (e) {
throw PassageError.fromObject(object: e);
}
}

@override
Future<MagicLink> changePhone(String newPhone) async {
Future<MagicLink> changePhone(String newPhone, String? language) async {
try {
final magicLinkId = await methodChannel
.invokeMethod<String>('changePhone', {'newPhone': newPhone});
.invokeMethod<String>('changePhone', {'newPhone': newPhone, 'language': language});
return MagicLink(magicLinkId!);
} catch (e) {
throw PassageError.fromObject(object: e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ abstract class PassageFlutterPlatform extends PlatformInterface {

// OTP METHODS

Future<String> newRegisterOneTimePasscode(String identifier) {
Future<String> newRegisterOneTimePasscode(String identifier, String? language) {
throw UnimplementedError(
'newRegisterOneTimePasscode() has not been implemented.');
}

Future<String> newLoginOneTimePasscode(String identifier) {
Future<String> newLoginOneTimePasscode(String identifier, String? language) {
throw UnimplementedError(
'newLoginOneTimePasscode() has not been implemented.');
}
Expand All @@ -71,12 +71,12 @@ abstract class PassageFlutterPlatform extends PlatformInterface {

// MAGIC LINK METHODS

Future<String> newRegisterMagicLink(String identifier) {
Future<String> newRegisterMagicLink(String identifier, String? language) {
throw UnimplementedError(
'newRegisterMagicLink() has not been implemented.');
}

Future<String> newLoginMagicLink(String identifier) {
Future<String> newLoginMagicLink(String identifier, String? language) {
throw UnimplementedError('newLoginMagicLink() has not been implemented.');
}

Expand Down Expand Up @@ -153,11 +153,11 @@ abstract class PassageFlutterPlatform extends PlatformInterface {
throw UnimplementedError('editPasskeyName() has not been implemented.');
}

Future<MagicLink> changeEmail(String newEmail) {
Future<MagicLink> changeEmail(String newEmail, String? language) {
throw UnimplementedError('changeEmail() has not been implemented.');
}

Future<MagicLink> changePhone(String newPhone) {
Future<MagicLink> changePhone(String newPhone, String? language) {
throw UnimplementedError('changePhone() has not been implemented.');
}

Expand Down
Loading
Loading