1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

App | Fix | Setup and save config after create new account (#2327)

This commit is contained in:
Evgenii Kozlov 2022-06-10 11:13:16 +03:00 committed by GitHub
parent 14366076f6
commit 318900033c
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 136 additions and 94 deletions

View file

@ -229,12 +229,12 @@ object SetupNewAccountModule {
@Provides
@PerScreen
fun provideCreateAccountUseCase(
repository: AuthRepository
): CreateAccount {
return CreateAccount(
repository = repository
)
}
repository: AuthRepository,
configStorage: ConfigStorage
): CreateAccount = CreateAccount(
repository = repository,
configStorage = configStorage
)
}
@Module

View file

@ -17,7 +17,9 @@ class AuthCacheDataStore(private val cache: AuthCache) : AuthDataStore {
throw UnsupportedOperationException()
}
override suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): AccountEntity {
override suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): AccountSetup {
throw UnsupportedOperationException()
}

View file

@ -23,7 +23,11 @@ class AuthDataRepository(
name: String,
avatarPath: String?,
invitationCode: String
): Account = factory.remote.createAccount(name, avatarPath, invitationCode).toDomain()
): AccountSetup = factory.remote.createAccount(
name = name,
avatarPath = avatarPath,
invitationCode = invitationCode
)
override suspend fun deleteAccount(): AccountStatus = factory.remote.deleteAccount()
override suspend fun restoreAccount(): AccountStatus = factory.remote.restoreAccount()

View file

@ -12,7 +12,7 @@ interface AuthDataStore {
suspend fun startAccount(id: String, path: String): AccountSetup
suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): AccountEntity
suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): AccountSetup
suspend fun deleteAccount() : AccountStatus
suspend fun restoreAccount() : AccountStatus

View file

@ -8,7 +8,7 @@ import kotlinx.coroutines.flow.Flow
interface AuthRemote {
suspend fun startAccount(id: String, path: String): AccountSetup
suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): AccountEntity
suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): AccountSetup
suspend fun deleteAccount() : AccountStatus
suspend fun restoreAccount() : AccountStatus
suspend fun recoverAccount()

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.AccountSetup
import com.anytypeio.anytype.core_models.AccountStatus
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.data.auth.model.AccountEntity
@ -17,7 +18,11 @@ class AuthRemoteDataStore(
name: String,
avatarPath: String?,
invitationCode: String
) = authRemote.createAccount(name, avatarPath, invitationCode)
) : AccountSetup = authRemote.createAccount(
name = name,
avatarPath = avatarPath,
invitationCode = invitationCode
)
override suspend fun deleteAccount(): AccountStatus = authRemote.deleteAccount()

View file

@ -1,23 +1,30 @@
package com.anytypeio.anytype.data
import com.anytypeio.anytype.core_models.Account
import com.anytypeio.anytype.core_models.AccountSetup
import com.anytypeio.anytype.core_models.AccountStatus
import com.anytypeio.anytype.core_models.FeaturesConfig
import com.anytypeio.anytype.core_models.StubAccount
import com.anytypeio.anytype.core_models.StubAccountSetup
import com.anytypeio.anytype.core_models.StubConfig
import com.anytypeio.anytype.core_models.StubFeatureConfig
import com.anytypeio.anytype.data.auth.model.AccountEntity
import com.anytypeio.anytype.data.auth.model.WalletEntity
import com.anytypeio.anytype.data.auth.repo.*
import com.anytypeio.anytype.data.auth.repo.AuthCache
import com.anytypeio.anytype.data.auth.repo.AuthCacheDataStore
import com.anytypeio.anytype.data.auth.repo.AuthDataRepository
import com.anytypeio.anytype.data.auth.repo.AuthDataStoreFactory
import com.anytypeio.anytype.data.auth.repo.AuthRemote
import com.anytypeio.anytype.data.auth.repo.AuthRemoteDataStore
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.*
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.stub
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.verifyZeroInteractions
class AuthDataRepositoryTest {
@ -29,8 +36,6 @@ class AuthDataRepositoryTest {
lateinit var repo: AuthDataRepository
val config = StubConfig()
@Before
fun setup() {
MockitoAnnotations.openMocks(this)
@ -86,14 +91,16 @@ class AuthDataRepositoryTest {
val name = MockDataFactory.randomString()
val account = AccountEntity(
id = name,
name = MockDataFactory.randomString(),
color = null
)
val setup = StubAccountSetup()
authRemote.stub {
onBlocking { createAccount(name = name, avatarPath = path, invitationCode = "code") } doReturn account
onBlocking {
createAccount(
name = name,
avatarPath = path,
invitationCode = "code"
)
} doReturn setup
}
repo.createAccount(

View file

@ -18,4 +18,6 @@ dependencies {
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
testImplementation unitTestDependencies.coroutineTesting
testImplementation project(":test:core-models-stub")
}

View file

@ -4,30 +4,28 @@ import com.anytypeio.anytype.core_models.Account
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.config.ConfigStorage
/**
* Creates an account, then stores it and sets as current user account.
*/
open class CreateAccount(
private val repository: AuthRepository
) : BaseUseCase<Account, CreateAccount.Params>() {
private val repository: AuthRepository,
private val configStorage: ConfigStorage,
) : BaseUseCase<Account, CreateAccount.Params>() {
override suspend fun run(params: Params) = try {
repository.createAccount(
override suspend fun run(params: Params) = safe {
val setup = repository.createAccount(
name = params.name,
avatarPath = params.avatarPath,
invitationCode = params.invitationCode
).let { account ->
with(repository) {
saveAccount(account)
setCurrentAccount(account.id)
account
}
}.let {
Either.Right(it)
)
with(repository) {
saveAccount(setup.account)
setCurrentAccount(setup.account.id)
}
} catch (e: Throwable) {
Either.Left(e)
configStorage.set(setup.config)
setup.account
}
/**

View file

@ -17,7 +17,11 @@ interface AuthRepository {
*/
suspend fun startAccount(id: String, path: String): AccountSetup
suspend fun createAccount(name: String, avatarPath: String?, invitationCode: String): Account
suspend fun createAccount(
name: String,
avatarPath: String?,
invitationCode: String
): AccountSetup
suspend fun deleteAccount() : AccountStatus
suspend fun restoreAccount() : AccountStatus

View file

@ -2,8 +2,10 @@ package com.anytypeio.anytype.domain.auth
import com.anytypeio.anytype.core_models.Account
import com.anytypeio.anytype.core_models.CoroutineTestRule
import com.anytypeio.anytype.core_models.StubAccountSetup
import com.anytypeio.anytype.domain.auth.interactor.CreateAccount
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.stub
@ -27,45 +29,48 @@ class CreateAccountTest {
@Mock
lateinit var repo: AuthRepository
@Mock
lateinit var configStorage: ConfigStorage
lateinit var createAccount: CreateAccount
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
createAccount = CreateAccount(repository = repo)
createAccount = CreateAccount(
repository = repo,
configStorage = configStorage
)
}
@Test
fun `should create account and save it and set as current user account`() = runBlocking {
fun `should create account and save it and set as current user account and save config in storage`() =
runBlocking {
val name = MockDataFactory.randomString()
val name = MockDataFactory.randomString()
val path = null
val path = null
val code = "code"
val code = "code"
val account = Account(
id = MockDataFactory.randomUuid(),
name = MockDataFactory.randomString(),
avatar = null,
color = null
)
val setup = StubAccountSetup()
val param = CreateAccount.Params(
name = name,
avatarPath = path,
invitationCode = code
)
val param = CreateAccount.Params(
name = name,
avatarPath = path,
invitationCode = code
)
repo.stub {
onBlocking { createAccount(name, path, code) } doReturn account
repo.stub {
onBlocking { createAccount(name, path, code) } doReturn setup
}
createAccount.run(param)
verify(repo, times(1)).createAccount(name, path, code)
verify(repo, times(1)).saveAccount(setup.account)
verify(repo, times(1)).setCurrentAccount(setup.account.id)
verifyNoMoreInteractions(repo)
verify(configStorage, times(1)).set(setup.config)
}
createAccount.run(param)
verify(repo, times(1)).createAccount(name, path, code)
verify(repo, times(1)).saveAccount(account)
verify(repo, times(1)).setCurrentAccount(account.id)
verifyNoMoreInteractions(repo)
}
}

View file

@ -7,7 +7,39 @@ import com.anytypeio.anytype.core_models.Config
import com.anytypeio.anytype.core_models.FeaturesConfig
import com.anytypeio.anytype.middleware.mappers.core
fun Rpc.Account.Select.Response.core(): AccountSetup {
fun Rpc.Account.Create.Response.toAccountSetup() : AccountSetup {
val acc = account
checkNotNull(acc) { "Account can't be empty" }
val configuration = acc.config
checkNotNull(configuration) { "Config can't be empty" }
val info = acc.info
checkNotNull(info) { "Info can't be empty" }
val status = acc.status
checkNotNull(status) { "Status can't be empty" }
return AccountSetup(
account = Account(
id = acc.id,
name = acc.name,
color = acc.avatar?.color,
avatar = null
),
features = FeaturesConfig(
enableDataView = configuration.enableDataview,
enableDebug = configuration.enableDebug,
enableChannelSwitch = configuration.enableReleaseChannelSwitch,
enableSpaces = configuration.enableSpaces
),
config = Config(
home = info.homeObjectId,
profile = info.profileObjectId,
gateway = info.gatewayUrl
),
status = status.core()
)
}
fun Rpc.Account.Select.Response.toAccountSetup(): AccountSetup {
val acc = account
checkNotNull(acc) { "Account can't be empty" }
val configuration = acc.config

View file

@ -29,15 +29,11 @@ class AuthMiddleware(
name: String,
avatarPath: String?,
invitationCode: String
) = withContext(Dispatchers.IO) {
middleware.accountCreate(name, avatarPath, invitationCode).let { response ->
AccountEntity(
id = response.id,
name = response.name,
color = response.avatar?.color
)
}
}
) : AccountSetup = middleware.accountCreate(
name = name,
path = avatarPath,
invitationCode = invitationCode
)
override suspend fun deleteAccount(): AccountStatus = middleware.accountDelete()
override suspend fun restoreAccount(): AccountStatus = middleware.accountRestore()

View file

@ -25,7 +25,7 @@ import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.Response
import com.anytypeio.anytype.core_models.SearchResult
import com.anytypeio.anytype.middleware.BuildConfig
import com.anytypeio.anytype.middleware.auth.core
import com.anytypeio.anytype.middleware.auth.toAccountSetup
import com.anytypeio.anytype.middleware.const.Constants
import com.anytypeio.anytype.middleware.mappers.MObjectType
import com.anytypeio.anytype.middleware.mappers.MRelation
@ -49,29 +49,16 @@ class Middleware(
name: String,
path: String?,
invitationCode: String
): CreateAccountResponse {
): AccountSetup {
val request = Rpc.Account.Create.Request(
name = name,
alphaInviteCode = invitationCode,
avatarLocalPath = path
)
if (BuildConfig.DEBUG) logRequest(request)
val response = service.accountCreate(request)
if (BuildConfig.DEBUG) logResponse(response)
val acc = response.account
checkNotNull(acc)
return CreateAccountResponse(
acc.id,
acc.name,
acc.avatar
)
return response.toAccountSetup()
}
@Throws(Exception::class)
@ -117,7 +104,7 @@ class Middleware(
if (BuildConfig.DEBUG) logRequest(request)
val response = service.accountSelect(request)
if (BuildConfig.DEBUG) logResponse(response)
return response.core()
return response.toAccountSetup()
}
@Throws(Exception::class)