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

Add unit test trying to reproduce App.currentUser returning invalid user. #7618

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@ import androidx.test.platform.app.InstrumentationRegistry
import io.realm.admin.ServerAdmin
import io.realm.entities.SyncStringOnly
import io.realm.exceptions.RealmFileException
import io.realm.internal.network.OkHttpNetworkTransport
import io.realm.internal.objectstore.OsJavaNetworkTransport
import io.realm.log.LogLevel
import io.realm.log.RealmLog
import io.realm.mongodb.*
import io.realm.mongodb.sync.SyncConfiguration
import io.realm.mongodb.sync.testSchema
import io.realm.mongodb.sync.SyncConfiguration
import io.realm.mongodb.sync.SyncSession
import io.realm.rule.BlockingLooperThread
import org.bson.codecs.StringCodec
import org.bson.codecs.configuration.CodecRegistries
Expand All @@ -45,6 +50,7 @@ class AppTests {
@Before
fun setUp() {
Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)
RealmLog.setLevel(LogLevel.DEBUG)
app = TestApp()
admin = ServerAdmin(app)
}
Expand Down Expand Up @@ -197,6 +203,134 @@ class AppTests {
assertNull(app.currentUser())
}

@Test
fun currentUser_availableIfJustExpired() = looperThread.runBlocking {
app.close()
Realm.init(InstrumentationRegistry.getInstrumentation().targetContext)
app = TestApp(object: OsJavaNetworkTransport() {
override fun sendRequestAsync(method: String,
url: String,
timeoutMs: Long,
headers: MutableMap<String, String>,
body: String,
completionPtr: Long) {
val response = executeRequest(method, url, timeoutMs, headers, body)
handleResponse(response, completionPtr)
}

override fun executeRequest(
method: String,
url: String,
timeoutMs: Long,
headers: MutableMap<String, String>,
body: String
): Response {
var result = ""
var code = 200
when {
url.endsWith("/providers/${Credentials.Provider.ANONYMOUS.id}/login") -> {
// This token expires on Sunday 10. May 2020 22:23:28
result = """
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODM5NjcyMDgsImlhdCI6MTU4Mzk2NTQwOCwiaXNzIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWEzIiwic3RpdGNoX2RldklkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic3RpdGNoX2RvbWFpbklkIjoiNWU2OTYzZGVhZmVhNjMyNTQ1ODFjMDI1Iiwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoiYWNjZXNzIn0.J4mp8LnlsxTQRV_7W2Er4qY0tptR76PJGG1k6HSMmUYqgfpJC2Fnbcf1VCoebzoNolH2-sr8AHDVBBCyjxRjqoY9OudFHmWZKmhDV1ysxPP4XmID0nUuN45qJSO8QEAqoOmP1crXjrUZWedFw8aaCZE-bxYfvcDHyjBcbNKZqzawwUw2PyTOlrNjgs01k2J4o5a5XzYkEsJuzr4_8UqKW6zXvYj24UtqnqoYatW5EzpX63m2qig8AcBwPK4ZHb5wEEUdf4QZxkRY5QmTgRHP8SSqVUB_mkHgKaizC_tSB3E0BekaDfLyWVC1taAstXJNfzgFtLI86AzuXS2dCiCfqQ",
"refresh_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjVlNjk2M2RmYWZlYTYzMjU0NTgxYzAyNiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODkxNDk0MDgsImlhdCI6MTU4Mzk2NTQwOCwic3RpdGNoX2RhdGEiOm51bGwsInN0aXRjaF9kZXZJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInN0aXRjaF9kb21haW5JZCI6IjVlNjk2M2RlYWZlYTYzMjU0NTgxYzAyNSIsInN0aXRjaF9pZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMyIsInN0aXRjaF9pZGVudCI6eyJpZCI6IjVlNjk2NGUwYWZlYTYzMjU0NTgxYzFhMC1oaWF2b3ZkbmJxbGNsYXBwYnl1cmJpaW8iLCJwcm92aWRlcl90eXBlIjoiYW5vbi11c2VyIiwicHJvdmlkZXJfaWQiOiI1ZTY5NjNlMGFmZWE2MzI1NDU4MWMwNGEifSwic3ViIjoiNWU2OTY0ZTBhZmVhNjMyNTQ1ODFjMWExIiwidHlwIjoicmVmcmVzaCJ9.FhLdpmL48Mw0SyUKWuaplz3wfeS8TCO8S7I9pIJenQww9nPqQ7lIvykQxjCCtinGvsZIJKt_7R31xYCq4Jp53Nw81By79IwkXtO7VXHPsXXZG5_2xV-s0u44e85sYD5su_H-xnx03sU2piJbWJLSB8dKu3rMD4mO-S0HNXCCAty-JkYKSaM2-d_nS8MNb6k7Vfm7y69iz_uwHc-bb_1rPg7r827K6DEeEMF41Hy3Nx1kCdAUOM9-6nYv3pZSU1PFrGYi2uyTXPJ7R7HigY5IGHWd0hwONb_NUr4An2omqfvlkLEd77ut4V9m6mExFkoKzRz7shzn-IGkh3e4h7ECGA",
"user_id": "5e6964e0afea63254581c1a1",
"device_id": "000000000000000000000000"
}
""".trimIndent()
}
url.endsWith("/auth/profile") -> {
result = """
{
"user_id": "5e6964e0afea63254581c1a1",
"domain_id": "000000000000000000000000",
"identities": [
{
"id": "5e68f51ade5ba998bb17500d",
"provider_type": "local-userpass",
"provider_id": "000000000000000000000003",
"provider_data": {
"email": "[email protected]"
}
}
],
"data": {
"email": "[email protected]"
},
"type": "normal",
"roles": [
{
"role_name": "GROUP_OWNER",
"group_id": "5e68f51e087b1b33a53f56d5"
}
]
}
""".trimIndent()
}
url.endsWith("/location") -> {
result = """
{ "deployment_model" : "GLOBAL",
"location": "US-VA",
"hostname": "http://localhost:9090",
"ws_hostname": "ws://localhost:9090"
}
""".trimIndent()
}
url.endsWith("/session") -> {
code = 401
result = "fake: refresh token could not be refreshed"
}
else -> {
fail("Unexpected request url: $url")
}
}
val successHeaders: Map<String, String> = mapOf(Pair("Content-Type", "application/json"))
return OkHttpNetworkTransport.Response.httpResponse(code, successHeaders, result)
}

override fun sendStreamingRequest(request: Request): Response {
throw IllegalAccessError()
}
})

val creds = Credentials.anonymous()
val user: User = app.login(creds)
assertNotNull(app.currentUser())
assertEquals(1, app.allUsers().size)

val syncConfig = configFactory.createSyncConfigurationBuilder(user)
.testSchema(SyncStringOnly::class.java)
.errorHandler { session: SyncSession, error: AppException ->
assertEquals(ErrorCode.BAD_AUTHENTICATION, error.errorCode)
assertEquals("Unable to refresh the user access token.", error.errorMessage)
assertFalse(session.user.isLoggedIn)
assertEquals(User.State.REMOVED, session.user.state)
assertNull(app.currentUser())
assertEquals(0, app.allUsers().size)
looperThread.testComplete()
}
.build()
val realm = Realm.getInstance(syncConfig)
looperThread.closeAfterTest(realm)
}

@Test
fun currentUser_nullWhenSyncAuthenticationFails() = looperThread.runBlocking {
val user: User = app.registerUserAndLogin(TestHelper.getRandomEmail(), "123456")
admin.disableUser(user)
val syncConfig = configFactory.createSyncConfigurationBuilder(user)
.testSchema(SyncStringOnly::class.java)
.errorHandler { session: SyncSession, error: AppException ->
RealmLog.error(error.toString())
assertEquals(User.State.LOGGED_OUT, session.user.state)
assertNull(app.currentUser())
looperThread.testComplete()
}
.build()
val realm = Realm.getInstance(syncConfig)
looperThread.closeAfterTest(realm)
}

@Test
fun switchUser_nullThrows() {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class ServerAdmin(private val app: App) {

val JSON = MediaType.parse("application/json; charset=utf-8")

/**
* Disable an existing user on the server.
*/
fun disableUser(user: User) {
var request = Request.Builder()
.url("$baseUrl/groups/$groupId/apps/$appId/users/${user.id}/disable")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,3 @@ public boolean isOpen() {
}

}