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

ADST-598 #364

Merged
merged 3 commits into from
Oct 15, 2024
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
49 changes: 28 additions & 21 deletions account/src/main/kotlin/com/alfresco/content/account/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ data class Account(
val myFiles: String? = null,
) {
companion object {
private const val displayNameKey = "displayName"
private const val emailKey = "email"
private const val authTypeKey = "type"
private const val authConfigKey = "config"
private const val serverKey = "server"
private const val myFilesKey = "myFiles"
private const val DISPLAY_NAME_KEY = "displayName"
private const val EMAIL_KEY = "email"
private const val AUTH_TYPE_KEY = "type"
private const val AUTH_CONFIG_KEY = "config"
private const val SERVER_KEY = "server"
private const val MY_FILES_KEY = "myFiles"

fun createAccount(
context: Context,
Expand All @@ -40,12 +40,12 @@ data class Account(
val sharedSecure = SecureSharedPreferencesManager(context)

val b = Bundle()
b.putString(authTypeKey, authType)
b.putString(authConfigKey, authConfig)
b.putString(serverKey, serverUrl)
b.putString(displayNameKey, KEY_DISPLAY_NAME)
b.putString(emailKey, KEY_EMAIL)
b.putString(myFilesKey, myFiles)
b.putString(AUTH_TYPE_KEY, authType)
b.putString(AUTH_CONFIG_KEY, authConfig)
b.putString(SERVER_KEY, serverUrl)
b.putString(DISPLAY_NAME_KEY, KEY_DISPLAY_NAME)
b.putString(EMAIL_KEY, KEY_EMAIL)
b.putString(MY_FILES_KEY, myFiles)
val acc = AndroidAccount(id, context.getString(R.string.android_auth_account_type))

// Save credentials securely using the SecureSharedPreferencesManager
Expand All @@ -54,7 +54,11 @@ data class Account(
AccountManager.get(context).addAccountExplicitly(acc, KEY_PASSWORD, b)
}

fun update(context: Context, id: String, authState: String) {
fun update(
context: Context,
id: String,
authState: String,
) {
val am = AccountManager.get(context)
val acc = getAndroidAccount(context)
val sharedSecure = SecureSharedPreferencesManager(context)
Expand All @@ -81,16 +85,19 @@ data class Account(
sharedSecure.saveCredentials(email, authState, displayName)

am.setPassword(acc, KEY_PASSWORD)
am.setUserData(acc, displayNameKey, KEY_DISPLAY_NAME)
am.setUserData(acc, emailKey, KEY_EMAIL)
am.setUserData(acc, myFilesKey, myFiles)
am.setUserData(acc, DISPLAY_NAME_KEY, KEY_DISPLAY_NAME)
am.setUserData(acc, EMAIL_KEY, KEY_EMAIL)
am.setUserData(acc, MY_FILES_KEY, myFiles)

if (acc?.name != id) {
am.renameAccount(acc, id, null, null)
}
}

fun delete(context: Context, callback: () -> Unit) {
fun delete(
context: Context,
callback: () -> Unit,
) {
AccountManager.get(context)
.removeAccount(getAndroidAccount(context), null, {
callback()
Expand All @@ -108,12 +115,12 @@ data class Account(
return Account(
acc.name,
secureCredentials.second,
am.getUserData(acc, authTypeKey),
am.getUserData(acc, authConfigKey),
am.getUserData(acc, serverKey),
am.getUserData(acc, AUTH_TYPE_KEY),
am.getUserData(acc, AUTH_CONFIG_KEY),
am.getUserData(acc, SERVER_KEY),
secureCredentials.third,
secureCredentials.first,
am.getUserData(acc, myFilesKey),
am.getUserData(acc, MY_FILES_KEY),
)
}
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import android.os.Bundle

class Authenticator(context: Context) :
AbstractAccountAuthenticator(context) {

override fun getAuthTokenLabel(authTokenType: String?): String {
throw UnsupportedOperationException()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import android.os.IBinder
* when started.
*/
class AuthenticatorService : Service() {

private lateinit var authenticator: Authenticator

override fun onCreate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@ import androidx.security.crypto.MasterKey
* Marked as SecureSharedPreferencesManager
*/
class SecureSharedPreferencesManager(private val context: Context) {
private val masterKey: MasterKey =
MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()

private val masterKey: MasterKey = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()

fun saveCredentials(email: String, password: String, displayName: String) {
fun saveCredentials(
email: String,
password: String,
displayName: String,
) {
try {
val encryptedSharedPreferences = EncryptedSharedPreferences.create(
context,
KEY_PREF_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
val encryptedSharedPreferences =
EncryptedSharedPreferences.create(
context,
KEY_PREF_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)

encryptedSharedPreferences.edit()
.putString(KEY_EMAIL, email)
Expand All @@ -38,13 +43,14 @@ class SecureSharedPreferencesManager(private val context: Context) {

fun savePassword(password: String) {
try {
val encryptedSharedPreferences = EncryptedSharedPreferences.create(
context,
KEY_PREF_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
val encryptedSharedPreferences =
EncryptedSharedPreferences.create(
context,
KEY_PREF_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)

encryptedSharedPreferences.edit()
.putString(KEY_PASSWORD, password)
Expand All @@ -58,13 +64,14 @@ class SecureSharedPreferencesManager(private val context: Context) {

fun getSavedCredentials(): Triple<String, String, String>? {
try {
val encryptedSharedPreferences = EncryptedSharedPreferences.create(
context,
KEY_PREF_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
val encryptedSharedPreferences =
EncryptedSharedPreferences.create(
context,
KEY_PREF_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)

val email = encryptedSharedPreferences.getString(KEY_EMAIL, null)
val password = encryptedSharedPreferences.getString(KEY_PASSWORD, null)
Expand Down
9 changes: 5 additions & 4 deletions actions/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
plugins{
id('com.android.library')
id('kotlin-android')
id('kotlin-kapt')
id 'com.android.library'
id 'kotlin-android'
// id('kotlin-kapt')
id 'com.google.devtools.ksp'
}

android {
Expand Down Expand Up @@ -35,7 +36,7 @@ dependencies {
implementation libs.epoxy.core
implementation libs.mavericks

kapt libs.epoxy.processor
ksp libs.epoxy.processor

// Testing
testImplementation libs.junit
Expand Down
22 changes: 17 additions & 5 deletions actions/src/main/kotlin/com/alfresco/content/actions/Action.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ interface Action {
val eventName: EventName

suspend fun execute(context: Context): ParentEntry

suspend fun executeMulti(context: Context): Pair<ParentEntry, List<Entry>> {
return Pair(entry, entries)
}

fun copy(_entry: ParentEntry): Action

fun copy(_entries: List<Entry>): Action {
return this
}
Expand Down Expand Up @@ -139,18 +141,25 @@ interface Action {
}
}

fun showToast(view: View, anchorView: View? = null) {}
fun showToast(
view: View,
anchorView: View? = null,
) {}

fun maxFileNameInToast(view: View) =
view.context.resources.getInteger(R.integer.action_toast_file_name_max_length)
fun maxFileNameInToast(view: View) = view.context.resources.getInteger(R.integer.action_toast_file_name_max_length)

data class Error(val message: String)

class Exception(string: String) : kotlin.Exception(string)

companion object {
const val ERROR_FILE_SIZE_EXCEED = "File size exceed"
fun showActionToasts(scope: CoroutineScope, view: View?, anchorView: View? = null) {

fun showActionToasts(
scope: CoroutineScope,
view: View?,
anchorView: View? = null,
) {
scope.on<Action>(block = showToast(view, anchorView))
scope.on<Error> {
if (view != null) {
Expand All @@ -159,7 +168,10 @@ interface Action {
}
}

private fun <T : Action> showToast(view: View?, anchorView: View?): suspend (value: T) -> Unit {
private fun <T : Action> showToast(
view: View?,
anchorView: View?,
): suspend (value: T) -> Unit {
return { action: T ->
// Don't call on backstack views
if (view != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ data class ActionCaptureMedia(
override var entry: Entry,
override val icon: Int = R.drawable.ic_action_capture_photo,
override val title: Int = R.string.action_capture_media_title,
override val eventName: EventName = if (entry.uploadServer == UploadServerType.UPLOAD_TO_TASK) EventName.TaskCreateMedia else EventName.CreateMedia,
override val eventName: EventName =
if (entry.uploadServer == UploadServerType.UPLOAD_TO_TASK) {
EventName.TaskCreateMedia
} else {
EventName.CreateMedia
},
) : Action {

private val repository = OfflineRepository()

override suspend fun execute(context: Context): Entry {
Expand Down Expand Up @@ -60,6 +64,8 @@ data class ActionCaptureMedia(

override fun copy(_entry: ParentEntry): Action = copy(entry = _entry as Entry)

override fun showToast(view: View, anchorView: View?) =
Action.showToast(view, anchorView, R.string.action_upload_media_toast)
override fun showToast(
view: View,
anchorView: View?,
) = Action.showToast(view, anchorView, R.string.action_upload_media_toast)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,27 @@ data class ActionCreateFolder(
override val title: Int = R.string.action_create_folder,
override val eventName: EventName = EventName.CreateFolder,
) : Action {

override suspend fun execute(context: Context): Entry {
val result = showCreateFolderDialog(context) ?: throw CancellationException("User Cancellation")
return BrowseRepository().createFolder(result.name, result.description, entry.id, false)
}

private suspend fun showCreateFolderDialog(context: Context) = withContext(Dispatchers.Main) {
suspendCoroutine {
CreateFolderDialog.Builder(context, false, entry.name)
.onSuccess { title, description ->
it.resume(CreateMetadata(title, description))
}
.onCancel { it.resume(null) }
.show()
private suspend fun showCreateFolderDialog(context: Context) =
withContext(Dispatchers.Main) {
suspendCoroutine {
CreateFolderDialog.Builder(context, false, entry.name)
.onSuccess { title, description ->
it.resume(CreateMetadata(title, description))
}
.onCancel { it.resume(null) }
.show()
}
}
}

override fun copy(_entry: ParentEntry): Action = copy(entry = _entry as Entry)

override fun showToast(view: View, anchorView: View?) =
Action.showToast(view, anchorView, R.string.action_create_folder_toast, entry.name)
override fun showToast(
view: View,
anchorView: View?,
) = Action.showToast(view, anchorView, R.string.action_create_folder_toast, entry.name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ data class ActionCreateTask(
return TaskRepository().createTask(result.name, result.description)
}

private suspend fun showCreateTaskDialog(context: Context) = withContext(Dispatchers.Main) {
suspendCoroutine {
CreateTaskDialog.Builder(context, false, CreateMetadata(entry.name, entry.description ?: ""))
.onSuccess { title, description ->
it.resume(CreateMetadata(title, description))
}
.onCancel { it.resume(null) }
.show()
private suspend fun showCreateTaskDialog(context: Context) =
withContext(Dispatchers.Main) {
suspendCoroutine {
CreateTaskDialog.Builder(context, false, CreateMetadata(entry.name, entry.description ?: ""))
.onSuccess { title, description ->
it.resume(CreateMetadata(title, description))
}
.onCancel { it.resume(null) }
.show()
}
}
}

override fun copy(_entry: ParentEntry): Action = copy(entry = _entry as TaskEntry)
}
Loading
Loading