Skip to content

Commit

Permalink
Add support for User.delete(). (#957)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmelchior authored Aug 9, 2022
1 parent ac46dba commit 5d99b9d
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

### Enhancements
* Added support for `UUID` through a new property type: `RealmUUID`.
* [Sync] Add support for `User.delete()`, making it possible to delete user data on the server side (Issue [#491](https://github.com/realm/realm-kotlin/issues/491)).

### Fixed
* Missing proguard configuration for `CoreErrorUtils`. (Issue [#942](https://github.com/realm/realm-kotlin/issues/942))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ expect object RealmInterop {
fun realm_app_log_in_with_credentials(app: RealmAppPointer, credentials: RealmCredentialsPointer, callback: AppCallback<RealmUserPointer>)
fun realm_app_log_out(app: RealmAppPointer, user: RealmUserPointer, callback: AppCallback<Unit>)
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_clear_cached_apps()
fun realm_app_sync_client_get_default_file_path_for_realm(
app: RealmAppPointer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,26 @@ actual object RealmInterop {
)
}

actual fun realm_app_delete_user(
app: RealmAppPointer,
user: RealmUserPointer,
callback: AppCallback<Unit>
) {
checkedBooleanResult(
realm_wrapper.realm_app_delete_user(
app.cptr(),
user.cptr(),
staticCFunction { userData, error ->
handleAppCallback(userData, error) { /* No-op, returns Unit */ }
},
StableRef.create(callback).asCPointer(),
staticCFunction { userdata ->
disposeUserData<AppCallback<RealmUserPointer>>(userdata)
}
)
)
}

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 @@ -688,6 +688,14 @@ actual object RealmInterop {
realmc.realm_app_remove_user(app.cptr(), user.cptr(), callback)
}

actual fun realm_app_delete_user(
app: RealmAppPointer,
user: RealmUserPointer,
callback: AppCallback<Unit>
) {
realmc.realm_app_delete_user(app.cptr(), user.cptr(), callback)
}

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 @@ -88,6 +88,21 @@ public interface User {
// TODO Document how this method behave if offline
public suspend fun remove(): User

/**
* Permanently deletes this user from your Atlas App Services app.
*
* If the user was deleted successfully on Atlas, the user state will be set to
* [State.REMOVED] and any local Realm files owned by the user will be deleted. If
* the server request fails, the local state will not be modified.
*
* All user realms should be closed before calling this method.
*
* @throws IllegalStateException if the user was already removed or not logged in.
* @throws io.realm.kotlin.mongodb.exceptions.ServiceException if a failure occurred when
* communicating with App Services. See [AppException] for details.
*/
public suspend fun delete()

/**
* Two Users are considered equal if they have the same user identity and are associated
* with the same app.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,23 @@ public class UserImpl(
return this
}

override suspend fun delete() {
if (state != User.State.LOGGED_IN) {
throw IllegalStateException("User must be logged in, in order to be deleted.")
}
Channel<Result<Unit>>(1).use { channel ->
RealmInterop.realm_app_delete_user(
app.nativePointer,
nativePointer,
channelResultCallback<Unit, Unit>(channel) {
// No-op
}.freeze()
)
return@use channel.receive()
.getOrThrow()
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@

package io.realm.kotlin.test.mongodb.shared

import io.realm.kotlin.Realm
import io.realm.kotlin.entities.sync.SyncObjectWithAllTypes
import io.realm.kotlin.internal.platform.fileExists
import io.realm.kotlin.internal.platform.runBlocking
import io.realm.kotlin.mongodb.App
import io.realm.kotlin.mongodb.Credentials
import io.realm.kotlin.mongodb.User
import io.realm.kotlin.mongodb.sync.SyncConfiguration
import io.realm.kotlin.test.mongodb.TestApp
import io.realm.kotlin.test.mongodb.asTestApp
import io.realm.kotlin.test.util.TestHelper
import io.realm.kotlin.test.util.TestHelper.randomEmail
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
Expand Down Expand Up @@ -297,6 +302,57 @@ class UserTests {
}
}

@Test
fun deleteUser() {
runBlocking {
val user1 = createUserAndLogin()
val config = SyncConfiguration.create(
user1,
TestHelper.randomPartitionValue(),
setOf(SyncObjectWithAllTypes::class)
)
Realm.open(config).close()
assertTrue(fileExists(config.path))
assertEquals(user1, app.currentUser)
assertEquals(1, app.allUsers().size)
user1.delete()
assertEquals(User.State.REMOVED, user1.state)
assertNull(app.currentUser)
assertEquals(0, app.allUsers().size)
assertFalse(fileExists(config.path))
}
}

@Test
fun deleteUser_loggedOutThrows() {
runBlocking {
val user1 = createUserAndLogin()
val config = SyncConfiguration.create(
user1,
TestHelper.randomPartitionValue(),
setOf(SyncObjectWithAllTypes::class)
)
Realm.open(config).close()
user1.logOut()
assertTrue(fileExists(config.path))
assertFailsWith<IllegalStateException> {
user1.delete()
}
assertTrue(fileExists(config.path))
}
}

@Test
fun deleteUser_throwsIfUserAlreadyDeleted() {
runBlocking {
val user1 = createUserAndLogin()
user1.delete()
assertFailsWith<IllegalStateException> {
user1.delete()
}
}
}

// @Test
// fun getApiKeyAuthProvider() {
// val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), "123456")
Expand Down

0 comments on commit 5d99b9d

Please sign in to comment.