Skip to content

Commit

Permalink
[RKOTLIN-1083] Remove deprecated user methods (#1750)
Browse files Browse the repository at this point in the history
  • Loading branch information
clementetb authored May 21, 2024
1 parent 5c7c2a0 commit f2f1c87
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This release will bump the Realm file format 24. Opening a file with an older fo
* Removed property `RealmLog.level`. Log levels can be set with `RealmLog.setLevel`. (Issue [#1691](https://github.com/realm/realm-kotlin/issues/1691) [JIRA](https://jira.mongodb.org/browse/RKOTLIN-1038))
* Removed `LogConfiguration`. Log levels and custom loggers can be set with `RealmLog`. (Issue [#1691](https://github.com/realm/realm-kotlin/issues/1691) [JIRA](https://jira.mongodb.org/browse/RKOTLIN-1038))
* Removed deprecated `io.realm.kotlin.types.ObjectId`. Use `org.mongodb.kbson.BsonObjectId` or its type alias `org.mongodb.kbson.ObjectId` instead. (Issue [#1749](https://github.com/realm/realm-kotlin/issues/1749) [JIRA](https://jira.mongodb.org/browse/RKOTLIN-1082))
* [Sync] Removed deprecated methods `User.identity` and `User.provider`, user identities can be accessed with the already existing `User.identities`. (Issue [#1751](https://github.com/realm/realm-kotlin/issues/1751) [JIRA](https://jira.mongodb.org/browse/RKOTLIN-1083))
* [Sync] `App.allUsers` does no longer return a map, but only a list of users known locally. (Issue [#1751](https://github.com/realm/realm-kotlin/issues/1751) [JIRA](https://jira.mongodb.org/browse/RKOTLIN-1083))

### Enhancements
* Support for RealmLists and RealmDictionaries in `RealmAny`. (Issue [#1434](https://github.com/realm/realm-kotlin/issues/1434))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,9 @@ public interface App {
* Returns all known users that are either [User.State.LOGGED_IN] or [User.State.LOGGED_OUT].
* Only users that at some point logged into this device will be returned.
*
* @return a map of user identifiers and users known locally. User identifiers will match what
* is returned by [User.identity].
* @return a list of locally known users.
*/
public fun allUsers(): Map<String, User>
public fun allUsers(): List<User>

/**
* Log in as a user with the given credentials associated with an authentication provider.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,6 @@ public interface User {
*/
public val state: State

/**
* The server id of the user.
*
* This property has been deprecated in favor of [id] and will be replaced in a future release.
*/
@Deprecated("Use `User.id` instead", replaceWith = ReplaceWith("id"))
public val identity: String

/**
* The server id of the user.
*/
Expand All @@ -79,13 +71,6 @@ public interface User {
*/
public val identities: List<UserIdentity>

/**
* Returns the provider type used to log the user in.
* If a user logs out, the authentication provider last used to log the user in will still be returned.
*/
@Deprecated("Users might have multiple providers. This will return the provider of the first identity of the user", ReplaceWith("identities"))
public val provider: AuthenticationProvider

/**
* Returns the current access token for the user.
* If a user logs out, an empty access token is returned.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,11 @@ public class AppImpl(
?.let { UserImpl(it, this) }
override val sync: Sync by lazy { SyncImpl(nativePointer) }

override fun allUsers(): Map<String, User> {
val nativeUsers: List<RealmUserPointer> =
RealmInterop.realm_app_get_all_users(nativePointer)
val map = mutableMapOf<String, User>()
nativeUsers.map { ptr: RealmUserPointer ->
val user = UserImpl(ptr, this)
map[user.identity] = user
}
return map
}
override fun allUsers(): List<User> =
RealmInterop.realm_app_get_all_users(nativePointer)
.map { ptr: RealmUserPointer ->
UserImpl(ptr, this)
}

override suspend fun login(credentials: Credentials): User {
// suspendCoroutine doesn't allow freezing callback capturing continuation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import io.realm.kotlin.internal.interop.RealmInterop
import io.realm.kotlin.internal.interop.RealmUserPointer
import io.realm.kotlin.internal.interop.sync.CoreUserState
import io.realm.kotlin.internal.util.use
import io.realm.kotlin.mongodb.AuthenticationProvider
import io.realm.kotlin.mongodb.Credentials
import io.realm.kotlin.mongodb.Functions
import io.realm.kotlin.mongodb.User
Expand All @@ -41,16 +40,11 @@ public class UserImpl(
override val state: User.State
get() = fromCoreState(RealmInterop.realm_user_get_state(nativePointer))

// TODO Can maybe fail, but we could also cache the return value?
override val identity: String
get() = id
override val id: String
get() = RealmInterop.realm_user_get_identity(nativePointer)
override val loggedIn: Boolean
get() = RealmInterop.realm_user_is_logged_in(nativePointer)
@Deprecated("Property not stable, users might have multiple providers.", ReplaceWith("User.identities"))
override val provider: AuthenticationProvider
get() = identities.first().provider

override val accessToken: String
get() = RealmInterop.realm_user_get_access_token(nativePointer)
override val refreshToken: String
Expand Down Expand Up @@ -187,13 +181,13 @@ public class UserImpl(
if (other == null || this::class != other::class) return false

other as UserImpl
if (id != (other.id)) return false

if (identity != (other.identity)) return false
return app.configuration == other.app.configuration
}

override fun hashCode(): Int {
var result = identity.hashCode()
var result = id.hashCode()
result = 31 * result + app.configuration.appId.hashCode()
return result
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ 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 @@ -121,7 +120,7 @@ class AppTests {
@Suppress("LoopWithTooManyJumpStatements")
@Test
fun login_invalidCredentialsThrows() = runBlocking {
for (provider in AuthenticationProvider.values()) {
for (provider in AuthenticationProvider.entries) {
when (provider) {
AuthenticationProvider.ANONYMOUS -> {
// No user input, so invalid credentials are not possible.
Expand Down Expand Up @@ -164,50 +163,52 @@ class AppTests {
@Test
fun allUsers() = runBlocking {
assertEquals(0, app.allUsers().size)

val user1 = app.login(Credentials.anonymous())
var allUsers = app.allUsers()
assertEquals(1, allUsers.size)
assertTrue(allUsers.containsKey(user1.identity))
assertEquals(user1, allUsers[user1.identity])
assertTrue(allUsers.contains(user1))

// Only 1 anonymous user exists, so logging in again just returns the old one
val user2 = app.login(Credentials.anonymous())
allUsers = app.allUsers()
assertEquals(1, allUsers.size)
assertTrue(allUsers.containsKey(user2.identity))
assertTrue(allUsers.contains(user2))

val user3: User = app.asTestApp.createUserAndLogIn(TestHelper.randomEmail(), "123456")
allUsers = app.allUsers()
assertEquals(2, allUsers.size)
assertTrue(allUsers.containsKey(user3.identity))
assertTrue(allUsers.contains(user3))

// Logging out users that registered with email/password will just put them in LOGGED_OUT state
user3.logOut()
allUsers = app.allUsers()
assertEquals(2, allUsers.size)
assertTrue(allUsers.containsKey(user3.identity))
assertEquals(User.State.LOGGED_OUT, allUsers[user3.identity]!!.state)
assertTrue(allUsers.contains(user3))
assertEquals(User.State.LOGGED_OUT, user3.state)

// Logging out anonymous users will remove them completely
user1.logOut()
allUsers = app.allUsers()
assertEquals(1, allUsers.size)
assertFalse(allUsers.containsKey(user1.identity))
assertTrue(allUsers.contains(user3))
assertFalse(allUsers.contains(user2))
assertFalse(allUsers.contains(user1))
}

@Test
fun allUsers_retrieveRemovedUser() = runBlocking {
val user1: User = app.login(Credentials.anonymous())
val allUsers: Map<String, User> = app.allUsers()
val allUsers = app.allUsers()
assertEquals(1, allUsers.size)
user1.logOut()
assertEquals(1, allUsers.size)
val userCopy: User = allUsers[user1.identity] ?: fail("Could not find user")
val userCopy: User = allUsers.first()
assertEquals(user1, userCopy)
assertEquals(User.State.REMOVED, userCopy.state)
assertTrue(app.allUsers().isEmpty())
}
//

// @Test
// fun switchUser() {
// val user1: User = app.login(Credentials.anonymous())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class CredentialsTests {

@Test
fun allCredentials() {
AuthenticationProvider.values().flatMap {
AuthenticationProvider.entries.flatMap {
when (it) {
AuthenticationProvider.ANONYMOUS -> listOf(it to anonymous())
AuthenticationProvider.EMAIL_PASSWORD -> listOf(it to emailPassword())
Expand Down Expand Up @@ -103,7 +103,7 @@ class CredentialsTests {

@Test
fun allCredentials_emptyInputThrows() {
for (value in AuthenticationProvider.values()) {
for (value in AuthenticationProvider.entries) {
assertFailsWith<IllegalArgumentException>("$value failed") { // No arguments should be allow
when (value) {
AuthenticationProvider.ANONYMOUS -> throw IllegalArgumentException("Do nothing, no arguments")
Expand Down Expand Up @@ -267,29 +267,29 @@ class CredentialsTests {
assertNotNull(firstUser)
val reusedUser = app.login(Credentials.anonymous())
assertNotNull(reusedUser)
assertEquals(firstUser.identity, reusedUser.identity)
assertEquals(firstUser, reusedUser)

val newAnonymousUser1 = app.login(Credentials.anonymous(false))
assertNotNull(newAnonymousUser1)
assertNotEquals(firstUser.identity, newAnonymousUser1.identity)
assertNotEquals(firstUser, newAnonymousUser1)

val newAnonymousUser2 = app.login(Credentials.anonymous(false))
assertNotNull(newAnonymousUser2)
assertNotEquals(newAnonymousUser1.identity, newAnonymousUser2.identity)
assertNotEquals(newAnonymousUser1, newAnonymousUser2)
}
}

@Test
fun loginUsingCredentials() {
runBlocking {
AuthenticationProvider.values().forEach { provider ->
AuthenticationProvider.entries.forEach { provider ->
when (provider) {
AuthenticationProvider.ANONYMOUS -> {
val reusableUser = app.login(Credentials.anonymous())
assertNotNull(reusableUser)
val nonReusableUser = app.login(Credentials.anonymous(false))
assertNotNull(nonReusableUser)
assertNotEquals(reusableUser.identity, nonReusableUser.identity)
assertNotEquals(reusableUser, nonReusableUser)
}
AuthenticationProvider.API_KEY -> {
// Log in, create an API key, log out, log in with the key, compare users
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ class UserTests {
fun getProviderType() = runBlocking {
val email = randomEmail()
val emailUser = createUserAndLogin(email, "123456")
assertEquals(AuthenticationProvider.EMAIL_PASSWORD, emailUser.provider)
assertEquals(AuthenticationProvider.EMAIL_PASSWORD, emailUser.identities.first().provider)
emailUser.logOut()
// AuthenticationProvider is not removed once user is logged out
assertEquals(AuthenticationProvider.EMAIL_PASSWORD, emailUser.provider)
assertEquals(AuthenticationProvider.EMAIL_PASSWORD, emailUser.identities.first().provider)
}

@Test
Expand Down

0 comments on commit f2f1c87

Please sign in to comment.