Skip to content

Commit

Permalink
[RKOTLIN-1115] Add support for switching user (#1816)
Browse files Browse the repository at this point in the history
  • Loading branch information
rorbech authored Aug 7, 2024
1 parent fc7bad7 commit b6f141f
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 41 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* None.

### Enhancements
* None.
* [Sync] Add support for switching users with `App.switchUser(User)`. (Issue [#1813](https://github.com/realm/realm-kotlin/issues/1813)/[RKOTLIN-1115](https://jira.mongodb.org/browse/RKOTLIN-1115)).

### Fixed
* None.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ expect object RealmInterop {
fun realm_app_remove_user(app: RealmAppPointer, user: RealmUserPointer, callback: AppCallback<Unit>)
fun realm_app_delete_user(app: RealmAppPointer, user: RealmUserPointer, callback: AppCallback<Unit>)
fun realm_app_link_credentials(app: RealmAppPointer, user: RealmUserPointer, credentials: RealmCredentialsPointer, callback: AppCallback<RealmUserPointer>)
fun realm_app_switch_user(app: RealmAppPointer, user: RealmUserPointer)
fun realm_clear_cached_apps()
fun realm_app_sync_client_get_default_file_path_for_realm(
syncConfig: RealmSyncConfigurationPointer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,10 @@ actual object RealmInterop {
realmc.realm_app_link_user(app.cptr(), user.cptr(), credentials.cptr(), callback)
}

actual fun realm_app_switch_user(app: RealmAppPointer, user: RealmUserPointer) {
realmc.realm_app_switch_user(app.cptr(), user.cptr())
}

actual fun realm_app_get_current_user(app: RealmAppPointer): RealmUserPointer? {
val ptr = realmc.realm_app_get_current_user(app.cptr())
return nativePointerOrNull(ptr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2357,6 +2357,10 @@ actual object RealmInterop {
)
}

actual fun realm_app_switch_user(app: RealmAppPointer, user: RealmUserPointer) {
checkedBooleanResult(realm_wrapper.realm_app_switch_user(app.cptr(), user.cptr()))
}

actual fun realm_clear_cached_apps() {
realm_wrapper.realm_clear_cached_apps()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ public interface App {
*/
public suspend fun login(credentials: Credentials): User

/**
* Switch current user.
*
* @param user the user that should be the new current user. The user must be one of the users
* that are already logged in.
* @throws IllegalStateException If the [user] is not logged in.
*/
public fun switchUser(user: User)

/**
* Create a [Flow] of [AuthenticationChange]-events to receive notifications of updates to all
* app user authentication states: login, logout and removal.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ public class AppImpl(
}
}

override fun switchUser(user: User) {
Validation.isType<UserImpl>(user)
RealmInterop.realm_app_switch_user(this.nativePointer, user.nativePointer)
}

internal fun reportAuthenticationChange(user: User, change: User.State) {
val event: AuthenticationChange = when (change) {
User.State.LOGGED_OUT -> LoggedOutImpl(user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import kotlin.test.assertNotEquals
import kotlin.test.assertNull
import kotlin.test.assertSame
import kotlin.test.assertTrue
import kotlin.test.fail

class AppTests {

Expand Down Expand Up @@ -210,30 +211,30 @@ class AppTests {
assertTrue(app.allUsers().isEmpty())
}

// @Test
// fun switchUser() {
// val user1: User = app.login(Credentials.anonymous())
// assertEquals(user1, app.currentUser())
// val user2: User = app.login(Credentials.anonymous())
// assertEquals(user2, app.currentUser())
//
// assertEquals(user1, app.switchUser(user1))
// assertEquals(user1, app.currentUser())
// }
//
// @Test
// fun switchUser_throwIfUserNotLoggedIn() = runBlocking {
// val user1 = app.login(Credentials.anonymous())
// val user2 = app.login(Credentials.anonymous())
// assertEquals(user2, app.currentUser)
//
// user1.logOut()
// try {
// app.switchUser(user1)
// fail()
// } catch (ignore: IllegalArgumentException) {
// }
// }
@Test
fun switchUser() = runBlocking {
val user1: User = app.login(Credentials.anonymous())
assertEquals(user1, app.currentUser)
val user2: User = app.login(Credentials.anonymous())
assertEquals(user2, app.currentUser)

app.switchUser(user1)
assertEquals(user1, app.currentUser)
}

@Test
fun switchUser_throwIfUserNotLoggedIn() = runBlocking {
val user1 = app.login(Credentials.anonymous())
val user2 = app.login(Credentials.anonymous())
assertEquals(user2, app.currentUser)

user1.logOut()
try {
app.switchUser(user1)
fail()
} catch (ignore: IllegalStateException) {
}
}

@Test
fun currentUser_FallbackToNextValidUser() = runBlocking {
Expand Down Expand Up @@ -262,21 +263,6 @@ class AppTests {
assertNull(app.currentUser)
}

// @Test
// fun switchUser_nullThrows() {
// try {
// app.switchUser(TestHelper.getNull())
// fail()
// } catch (ignore: IllegalArgumentException) {
// }
// }
//
// @Ignore("Add this test once we have support for both EmailPassword and ApiKey Auth Providers")
// @Test
// fun switchUser_authProvidersLockUsers() {
// TODO("FIXME")
// }
//
@Test
fun authenticationChangeAsFlow() = runBlocking<Unit> {
val c = TestChannel<AuthenticationChange>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ class FunctionsTests {
runBlocking {
anonUser.logOut()
}
assertFailsWithMessage<ServiceException>("[Service][Unknown(4351)] unauthorized") {
assertFailsWithMessage<ServiceException>("unauthorized") {
runBlocking {
functions.call(FIRST_ARG_FUNCTION.name, 1, 2, 3)
}
Expand Down

0 comments on commit b6f141f

Please sign in to comment.