mirror of
https://github.com/etesync/android
synced 2025-07-08 23:58:27 +00:00
190 lines
7.6 KiB
Kotlin
190 lines
7.6 KiB
Kotlin
/*
|
||
* Copyright © 2013 – 2016 Ricki Hirner (bitfire web engineering).
|
||
* All rights reserved. This program and the accompanying materials
|
||
* are made available under the terms of the GNU Public License v3.0
|
||
* which accompanies this distribution, and is available at
|
||
* http://www.gnu.org/licenses/gpl.html
|
||
*/
|
||
|
||
package com.etesync.syncadapter.ui.setup
|
||
|
||
import android.accounts.Account
|
||
import android.accounts.AccountManager
|
||
import android.app.Activity
|
||
import android.app.Dialog
|
||
import android.app.ProgressDialog
|
||
import android.content.Context
|
||
import android.os.AsyncTask
|
||
import android.os.Bundle
|
||
import android.provider.CalendarContract
|
||
import androidx.appcompat.app.AlertDialog
|
||
import androidx.fragment.app.DialogFragment
|
||
import at.bitfire.ical4android.TaskProvider.Companion.TASK_PROVIDERS
|
||
import com.etesync.journalmanager.Crypto
|
||
import com.etesync.journalmanager.Exceptions
|
||
import com.etesync.syncadapter.*
|
||
import com.etesync.syncadapter.log.Logger
|
||
import com.etesync.syncadapter.model.CollectionInfo
|
||
import com.etesync.syncadapter.model.JournalEntity
|
||
import com.etesync.syncadapter.model.ServiceEntity
|
||
import com.etesync.syncadapter.ui.setup.BaseConfigurationFinder.Configuration
|
||
import com.etesync.syncadapter.utils.AndroidCompat
|
||
import com.etesync.syncadapter.utils.TaskProviderHandling
|
||
import java.util.logging.Level
|
||
|
||
class SetupEncryptionFragment : DialogFragment() {
|
||
|
||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||
val progress = ProgressDialog(activity)
|
||
progress.setTitle(R.string.setting_up_encryption)
|
||
progress.setMessage(getString(R.string.setting_up_encryption_content))
|
||
progress.isIndeterminate = true
|
||
progress.setCanceledOnTouchOutside(false)
|
||
isCancelable = false
|
||
return progress
|
||
}
|
||
|
||
override fun onCreate(savedInstanceState: Bundle?) {
|
||
super.onCreate(savedInstanceState)
|
||
|
||
SetupEncryptionLoader(context!!, arguments!!.getSerializable(KEY_CONFIG) as Configuration).execute()
|
||
}
|
||
|
||
private inner class SetupEncryptionLoader(internal val context: Context, internal val config: Configuration) : AsyncTask<Void, Void, Configuration>() {
|
||
|
||
override fun onPostExecute(result: Configuration) {
|
||
if (config.error != null && config.error is Exceptions.IntegrityException) {
|
||
Logger.log.severe("Wrong encryption password.")
|
||
AlertDialog.Builder(activity!!)
|
||
.setTitle(R.string.wrong_encryption_password)
|
||
.setIcon(R.drawable.ic_error_dark)
|
||
.setMessage(getString(R.string.wrong_encryption_password_content, config.error!!.localizedMessage))
|
||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||
// dismiss
|
||
}.show()
|
||
} else {
|
||
try {
|
||
if (createAccount(config.userName, config)) {
|
||
activity!!.setResult(Activity.RESULT_OK)
|
||
activity!!.finish()
|
||
}
|
||
} catch (e: InvalidAccountException) {
|
||
Logger.log.severe("Account creation failed!")
|
||
AlertDialog.Builder(activity!!)
|
||
.setTitle(R.string.account_creation_failed)
|
||
.setIcon(R.drawable.ic_error_dark)
|
||
.setMessage(e.localizedMessage)
|
||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||
// dismiss
|
||
}.show()
|
||
}
|
||
|
||
}
|
||
|
||
dismissAllowingStateLoss()
|
||
}
|
||
|
||
override fun doInBackground(vararg aVoids: Void): Configuration {
|
||
Logger.log.info("Started deriving key")
|
||
config.password = Crypto.deriveKey(config.userName, config.rawPassword!!)
|
||
Logger.log.info("Finished deriving key")
|
||
config.error = null
|
||
|
||
try {
|
||
val cryptoManager: Crypto.CryptoManager
|
||
|
||
val userInfo = config.userInfo
|
||
if (userInfo != null) {
|
||
Logger.log.info("Fetched userInfo for " + config.userName)
|
||
cryptoManager = Crypto.CryptoManager(userInfo.version!!.toInt(), config.password!!, "userInfo")
|
||
userInfo.verify(cryptoManager)
|
||
config.keyPair = Crypto.AsymmetricKeyPair(userInfo.getContent(cryptoManager)!!, userInfo.pubkey!!)
|
||
}
|
||
} catch (e: Exception) {
|
||
e.printStackTrace()
|
||
config.error = e
|
||
}
|
||
|
||
return config
|
||
}
|
||
}
|
||
|
||
|
||
@Throws(InvalidAccountException::class)
|
||
protected fun createAccount(accountName: String, config: BaseConfigurationFinder.Configuration): Boolean {
|
||
val account = Account(accountName, App.accountType)
|
||
|
||
// create Android account
|
||
Logger.log.log(Level.INFO, "Creating Android account with initial config", arrayOf(account, config.userName, config.url))
|
||
|
||
val accountManager = AccountManager.get(context)
|
||
if (!accountManager.addAccountExplicitly(account, config.password, null))
|
||
return false
|
||
|
||
AccountSettings.setUserData(accountManager, account, config.url, config.userName)
|
||
|
||
// add entries for account to service DB
|
||
Logger.log.log(Level.INFO, "Writing account configuration to database", config)
|
||
try {
|
||
val settings = AccountSettings(context!!, account)
|
||
|
||
settings.authToken = config.authtoken!!
|
||
if (config.keyPair != null) {
|
||
settings.keyPair = config.keyPair!!
|
||
}
|
||
|
||
// insert CardDAV service
|
||
insertService(accountName, CollectionInfo.Type.ADDRESS_BOOK)
|
||
|
||
// contact sync is automatically enabled by isAlwaysSyncable="true" in res/xml/sync_contacts.xml
|
||
settings.setSyncInterval(App.addressBooksAuthority, Constants.DEFAULT_SYNC_INTERVAL.toLong())
|
||
|
||
// insert CalDAV service
|
||
insertService(accountName, CollectionInfo.Type.CALENDAR)
|
||
|
||
// calendar sync is automatically enabled by isAlwaysSyncable="true" in res/xml/sync_contacts.xml
|
||
settings.setSyncInterval(CalendarContract.AUTHORITY, Constants.DEFAULT_SYNC_INTERVAL.toLong())
|
||
|
||
TASK_PROVIDERS.forEach {
|
||
// enable task sync if OpenTasks is installed
|
||
// further changes will be handled by PackageChangedReceiver
|
||
TaskProviderHandling.updateTaskSync(context!!, it)
|
||
}
|
||
|
||
} catch (e: InvalidAccountException) {
|
||
Logger.log.log(Level.SEVERE, "Couldn't access account settings", e)
|
||
AndroidCompat.removeAccount(accountManager, account)
|
||
throw e
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
protected fun insertService(accountName: String, serviceType: CollectionInfo.Type) {
|
||
val info = Configuration.ServiceInfo()
|
||
val data = (requireContext().applicationContext as App).data
|
||
|
||
// insert service
|
||
val serviceEntity = ServiceEntity.fetchOrCreate(data, accountName, serviceType)
|
||
|
||
// insert collections
|
||
for (collection in info.collections.values) {
|
||
collection.serviceID = serviceEntity.id
|
||
val journalEntity = JournalEntity(data, collection)
|
||
data.insert(journalEntity)
|
||
}
|
||
}
|
||
|
||
companion object {
|
||
private val KEY_CONFIG = "config"
|
||
|
||
fun newInstance(config: BaseConfigurationFinder.Configuration): SetupEncryptionFragment {
|
||
val frag = SetupEncryptionFragment()
|
||
val args = Bundle(1)
|
||
args.putSerializable(KEY_CONFIG, config)
|
||
frag.arguments = args
|
||
return frag
|
||
}
|
||
}
|
||
}
|