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:
parent
14366076f6
commit
318900033c
14 changed files with 136 additions and 94 deletions
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -18,4 +18,6 @@ dependencies {
|
|||
|
||||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
|
||||
testImplementation unitTestDependencies.coroutineTesting
|
||||
|
||||
testImplementation project(":test:core-models-stub")
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue