Skip to content

Commit

Permalink
Merge branch 'develop' into fix/session-manager-missing-session-error…
Browse files Browse the repository at this point in the history
…-cherry-pick
  • Loading branch information
MohamadJaara authored Nov 16, 2023
2 parents c88018e + 3a9836b commit ccfb388
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ object CoreLogger {
CryptographyLogger.init(config = config)
PersistenceLogger.init(config = config)
}

fun setLoggingLevel(level: KaliumLogLevel) {
kaliumLoggerConfig.setLogLevel(level)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import com.wire.kalium.logic.data.featureConfig.AppLockModel
import com.wire.kalium.logic.data.featureConfig.Status
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.nullableFold
import kotlin.time.Duration.Companion.seconds

class AppLockConfigHandler(
private val userConfigRepository: UserConfigRepository
Expand All @@ -37,8 +36,8 @@ class AppLockConfigHandler(
},
{
val newStatus = appLockConfig.status == Status.ENABLED
((it.isEnabled != newStatus) ||
(newStatus && it.timeout != appLockConfig.inactivityTimeoutSecs.seconds))
if (it.isEnabled != newStatus) true
else it.isStatusChanged
}
)
return userConfigRepository.setAppLockStatus(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class AppLockConfigHandlerTest {
}

@Test
fun givenNewStatusSameAsCurrent_whenHandlingTheEvent_ThenSetAppLockWithStatusChangedFalse() {
fun givenNewStatusSameAsCurrent_whenHandlingTheEvent_ThenSetAppLockWithOldStatusChangedValue() {
val appLockModel = AppLockModel(Status.ENABLED, 44)
val (arrangement, appLockConfigHandler) = Arrangement()
.withAppLocked()
Expand All @@ -99,30 +99,7 @@ class AppLockConfigHandlerTest {
.with(
eq(appLockModel.status.toBoolean()),
eq(appLockModel.inactivityTimeoutSecs),
eq(false)
)
.wasInvoked(exactly = once)
}

@Test
fun givenStatusEnabledAndTimeoutDifferentFromCurrent_whenHandlingTheEvent_ThenSetAppLockWithStatusChangedTrue() {
val appLockModel = AppLockModel(Status.ENABLED, 20)
val (arrangement, appLockConfigHandler) = Arrangement()
.withAppLocked()
.arrange()

appLockConfigHandler.handle(appLockModel)

verify(arrangement.userConfigRepository)
.function(arrangement.userConfigRepository::isTeamAppLockEnabled)
.wasInvoked(exactly = once)

verify(arrangement.userConfigRepository)
.function(arrangement.userConfigRepository::setAppLockStatus)
.with(
eq(appLockModel.status.toBoolean()),
eq(appLockModel.inactivityTimeoutSecs),
eq(true)
eq(appLockTeamConfigEnabled.isStatusChanged)
)
.wasInvoked(exactly = once)
}
Expand Down
10 changes: 6 additions & 4 deletions testservice/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ logging:

# The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL.
level: INFO
loggers:
com.wire.kalium: DEBUG

appenders:
- type: console
threshold: INFO
threshold: DEBUG
- type: file
threshold: INFO
logFormat: "%-6level [%d{HH:mm:ss.SSS}] [%t] %logger{5} - %X{code} %msg %n"
threshold: DEBUG
logFormat: "%-6level [%d{HH:mm:ss.SSS}] %X{code} %msg %n"
currentLogFilename: /var/log/kalium-testservice/application.log
archivedLogFilenamePattern: /var/log/kalium-testservice/application-%d{yyyy-MM-dd}.log
archivedFileCount: 7
timeZone: GMT+1
- type: file
threshold: ALL
logFormat: "%-6level [%d{HH:mm:ss.SSS}] [%t] %logger{5} - %X{code} %msg %n"
logFormat: "%-6level [%d{HH:mm:ss.SSS}] %X{code} %msg %n"
currentLogFilename: /var/log/kalium-testservice/application_debug.log
archivedLogFilenamePattern: /var/log/kalium-testservice/application_debug-%d{yyyy-MM-dd}.log
archivedFileCount: 7
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.testservice

import co.touchlab.kermit.LogWriter
import co.touchlab.kermit.Severity
import com.wire.kalium.testservice.managed.InstanceService
import org.slf4j.LoggerFactory

class KaliumLogWriter(private val instanceId: String) : LogWriter() {

private val log = LoggerFactory.getLogger(InstanceService::class.java.name)

override fun log(severity: Severity, message: String, tag: String, throwable: Throwable?) {
when (severity) {
Severity.Verbose -> log.debug("Instance $instanceId: $message")
Severity.Debug -> log.debug("Instance $instanceId: $message")
Severity.Info -> log.info("Instance $instanceId: $message")
Severity.Warn -> log.warn("Instance $instanceId: $message")
Severity.Error -> log.error("Instance $instanceId: $message $throwable")
Severity.Assert -> log.info("Instance $instanceId: $message")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import javax.ws.rs.container.AsyncResponse
import javax.ws.rs.container.ConnectionCallback
import javax.ws.rs.container.Suspended
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("/api/v1")
@Produces(MediaType.APPLICATION_JSON)
Expand Down Expand Up @@ -69,14 +70,23 @@ class InstanceLifecycle(
// handles unresponsive instances
ar.setTimeout(timeout, TimeUnit.SECONDS)
ar.setTimeoutHandler { asyncResponse: AsyncResponse ->
log.error("Async create instance request timed out after $timeout seconds")
asyncResponse.cancel()
instanceService.deleteInstance(instanceId)
log.error("Instance $instanceId: Async create instance request timed out after $timeout seconds")
asyncResponse.resume(
Response
.status(Response.Status.GATEWAY_TIMEOUT)
.entity("Instance $instanceId: Async create instance request timed out after $timeout seconds")
.build()
)
if (instanceService.getInstance(instanceId) != null) {
instanceService.deleteInstance(instanceId)
}
}
// handles client disconnect
ar.register(ConnectionCallback { disconnected: AsyncResponse? ->
log.error("Client disconnected from async create instance request")
instanceService.deleteInstance(instanceId)
log.error("Instance $instanceId: Client disconnected from async create instance request")
if (instanceService.getInstance(instanceId) != null) {
instanceService.deleteInstance(instanceId)
}
})

val createdInstance = try {
Expand All @@ -86,7 +96,7 @@ class InstanceLifecycle(
} catch (we: WebApplicationException) {
throw we
} catch (e: Exception) {
log.error("Could not create instance: " + e.message, e)
log.error("Instance $instanceId: Could not create instance: " + e.message, e)
throw WebApplicationException("Could not create instance: " + e.message)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package com.wire.kalium.testservice.managed
import com.codahale.metrics.Gauge
import com.codahale.metrics.MetricRegistry
import com.wire.kalium.logger.KaliumLogLevel
import com.wire.kalium.logger.KaliumLogger
import com.wire.kalium.logic.CoreLogger
import com.wire.kalium.logic.CoreLogic
import com.wire.kalium.logic.configuration.server.ServerConfig
Expand All @@ -39,6 +40,7 @@ import com.wire.kalium.logic.feature.client.RegisterClientUseCase
import com.wire.kalium.logic.feature.session.CurrentSessionResult
import com.wire.kalium.logic.featureFlags.KaliumConfigs
import com.wire.kalium.logic.functional.onFailure
import com.wire.kalium.testservice.KaliumLogWriter
import com.wire.kalium.testservice.TestserviceConfiguration
import com.wire.kalium.testservice.models.FingerprintResponse
import com.wire.kalium.testservice.models.Instance
Expand Down Expand Up @@ -134,18 +136,18 @@ class InstanceService(
)
}

@Suppress("LongMethod", "ThrowsCount")
suspend fun createInstance(instanceId: String, instanceRequest: InstanceRequest): Instance {
@Suppress("LongMethod", "ThrowsCount", "ComplexMethod")
suspend fun createInstance(instanceId: String, instanceRequest: InstanceRequest): Any {
val userAgent = "KaliumTestService/${System.getProperty("http.agent")}"
val before = System.currentTimeMillis()
val instancePath = System.getProperty("user.home") +
File.separator + ".testservice" + File.separator + instanceId
log.info("Instance $instanceId: Creating $instancePath")
val kaliumConfigs = KaliumConfigs(
developmentApiEnabled = false
developmentApiEnabled = instanceRequest.developmentApiEnabled ?: false
)
val coreLogic = CoreLogic(instancePath, kaliumConfigs, userAgent)
CoreLogger.setLoggingLevel(KaliumLogLevel.VERBOSE)
CoreLogger.init(KaliumLogger.Config(KaliumLogLevel.VERBOSE, listOf(KaliumLogWriter(instanceId))))

val serverConfig = if (instanceRequest.customBackend != null) {
ServerConfig.Links(
Expand Down Expand Up @@ -208,10 +210,8 @@ class InstanceService(
loginResult.authData.userId
}

var clientId: String? = null

log.info("Instance $instanceId: Register client device")
runBlocking {
val response = runBlocking {
coreLogic.sessionScope(userId) {
if (client.needsToRegisterClient()) {
when (val result = client.getOrRegister(
Expand All @@ -222,33 +222,50 @@ class InstanceService(
model = instanceRequest.deviceName
)
)) {
is RegisterClientResult.Failure ->
throw WebApplicationException("Instance $instanceId: Client registration failed")

is RegisterClientResult.Success -> {
clientId = result.client.id.value
val clientId = result.client.id.value
log.info("Instance $instanceId: Device $clientId successfully registered")
syncManager.waitUntilLive()

val startTime = System.currentTimeMillis()
val startupTime = startTime - before

val instance = Instance(
instanceRequest.backend,
clientId,
instanceId,
instanceRequest.name,
coreLogic,
instancePath,
instanceRequest.password,
startupTime,
startTime
)
instances.put(instanceId, instance)

syncManager.waitUntilLiveOrFailure().onFailure {
log.error("Instance $instanceId: Sync failed with $it")
}

return@runBlocking instance
}
is RegisterClientResult.Failure.TooManyClients ->
throw WebApplicationException("Instance $instanceId: Client registration failed, too many clients")
is RegisterClientResult.Failure.InvalidCredentials.Invalid2FA ->
throw WebApplicationException("Instance $instanceId: Client registration failed, invalid 2FA code")
is RegisterClientResult.Failure.InvalidCredentials.InvalidPassword ->
throw WebApplicationException("Instance $instanceId: Client registration failed, invalid password")
is RegisterClientResult.Failure.InvalidCredentials.Missing2FA ->
throw WebApplicationException("Instance $instanceId: Client registration failed, 2FA code needed for account")
is RegisterClientResult.Failure.PasswordAuthRequired ->
throw WebApplicationException("Instance $instanceId: Client registration failed, missing password")
is RegisterClientResult.Failure.Generic ->
throw WebApplicationException("Instance $instanceId: Client registration failed")
}
}
}
}

val instance = Instance(
instanceRequest.backend,
clientId,
instanceId,
instanceRequest.name,
coreLogic,
instancePath,
instanceRequest.password,
System.currentTimeMillis() - before,
System.currentTimeMillis()
)
instances.put(instanceId, instance)

return instance
return response
}

fun deleteInstance(id: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ data class InstanceRequest(
val name: String = "",
val password: String = "",
val verificationCode: String? = null,
val developmentApiEnabled: Boolean? = false,
)

0 comments on commit ccfb388

Please sign in to comment.