Skip to content

Commit

Permalink
Merge pull request #126 from itszechs/multi-drive-client
Browse files Browse the repository at this point in the history
Multiple drive clients support
  • Loading branch information
itszechs authored Dec 25, 2024
2 parents 57a0427 + 1a30c41 commit 176ecfe
Show file tree
Hide file tree
Showing 56 changed files with 2,106 additions and 686 deletions.
54 changes: 42 additions & 12 deletions app/src/main/java/zechs/drive/stream/data/local/AccountsDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,54 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import kotlinx.coroutines.flow.Flow
import zechs.drive.stream.data.model.Account
import zechs.drive.stream.data.model.AccountWithClient
import zechs.drive.stream.data.model.Client

@Dao
interface AccountsDao {

@Query("SELECT * FROM `accounts`")
suspend fun getAccounts(): List<Account>

@Query("SELECT * FROM `accounts` WHERE name = :name LIMIT 1")
suspend fun getAccount(name: String): Account?

@Query("UPDATE `accounts` SET accessToken = :accessToken WHERE refreshToken = :refreshToken")
suspend fun updateAccessToken(refreshToken: String, accessToken: String)

@Query("DELETE FROM `accounts` WHERE name = :name")
suspend fun deleteAccount(name: String)
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addClient(client: Client)

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addAccount(account: Account): Long
suspend fun addAccount(account: Account)

@Transaction
@Query("DELETE FROM clients WHERE id = :clientId")
suspend fun deleteClient(clientId: String)

@Query("SELECT * FROM clients")
fun getClients(): Flow<List<Client>>

@Transaction
@Query(
"SELECT accounts.*, clients.secret AS clientSecret, clients.redirectUri " +
"FROM accounts JOIN clients ON accounts.clientId = clients.id"
)
fun getAccounts(): Flow<List<AccountWithClient>>

@Transaction
@Query(
"SELECT accounts.*, clients.secret AS clientSecret, clients.redirectUri " +
"FROM accounts JOIN clients ON accounts.clientId = clients.id " +
"WHERE accounts.name = :accountName"
)
suspend fun getAccount(accountName: String): AccountWithClient?

@Query("UPDATE accounts SET name = :newName WHERE name = :oldName")
suspend fun updateAccountName(oldName: String, newName: String)

@Query("DELETE FROM accounts WHERE name = :accountName")
suspend fun deleteAccount(accountName: String)

@Transaction
@Query("UPDATE clients SET secret = :secret, redirectUri = :redirectUri WHERE id = :clientId")
suspend fun updateClient(clientId: String, secret: String, redirectUri: String)

@Query("UPDATE accounts SET accessToken = :newToken WHERE name = :accountName")
suspend fun updateAccessToken(accountName: String, newToken: String)

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package zechs.drive.stream.data.local
import androidx.room.Database
import androidx.room.RoomDatabase
import zechs.drive.stream.data.model.Account
import zechs.drive.stream.data.model.Client


@Database(
entities = [Account::class],
entities = [Account::class, Client::class],
version = 1,
exportSchema = false
)
Expand Down
35 changes: 0 additions & 35 deletions app/src/main/java/zechs/drive/stream/data/model/Account.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package zechs.drive.stream.data.model

import androidx.annotation.Keep
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

@Entity(tableName = "clients")
data class Client(
@PrimaryKey val id: String,
val secret: String,
val redirectUri: String
) {
fun isEmpty() = id.isEmpty() || secret.isEmpty() || redirectUri.isEmpty()
}

@Entity(
tableName = "accounts",
foreignKeys = [ForeignKey(
entity = Client::class,
parentColumns = ["id"],
childColumns = ["clientId"],
onDelete = ForeignKey.CASCADE
)],
indices = [Index("clientId")]
)
data class Account(
@PrimaryKey val name: String,
val refreshToken: String,
val accessToken: String,
val clientId: String
)

@Keep
data class AccountWithClient(
val name: String,
val clientId: String,
val clientSecret: String,
val redirectUri: String,
val refreshToken: String,
val accessToken: String
) {

@Ignore
var isDefault: Boolean = false

fun getDriveClient() = DriveClient(
clientId = clientId,
clientSecret = clientSecret,
redirectUri = redirectUri,
scopes = listOf("https://www.googleapis.com/auth/drive")
)

fun getAccessTokenResponse(): TokenResponse {
val type = object : TypeToken<TokenResponse>() {}.type
return Gson().fromJson(accessToken, type)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ data class DriveClient(
} catch (e: Exception) {
null
}

fun getClient() = Client(
id = clientId,
secret = clientSecret,
redirectUri = redirectUri
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package zechs.drive.stream.data.model

import com.google.errorprone.annotations.Keep

@Keep
data class TokenRequestBody(
val token: String
)
15 changes: 15 additions & 0 deletions app/src/main/java/zechs/drive/stream/data/remote/RevokeTokenApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package zechs.drive.stream.data.remote

import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
import zechs.drive.stream.data.model.TokenRequestBody

interface RevokeTokenApi {

@POST("/revoke")
suspend fun revokeToken(
@Body body: TokenRequestBody
): Response<Unit>

}
17 changes: 17 additions & 0 deletions app/src/main/java/zechs/drive/stream/di/ApiModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import zechs.drive.stream.BuildConfig
import zechs.drive.stream.data.model.StarredAdapter
import zechs.drive.stream.data.remote.DriveApi
import zechs.drive.stream.data.remote.GithubApi
import zechs.drive.stream.data.remote.RevokeTokenApi
import zechs.drive.stream.data.remote.TokenApi
import zechs.drive.stream.data.repository.DriveRepository
import zechs.drive.stream.data.repository.GithubRepository
Expand All @@ -23,6 +24,7 @@ import zechs.drive.stream.utils.SessionManager
import zechs.drive.stream.utils.util.Constants.Companion.GITHUB_API
import zechs.drive.stream.utils.util.Constants.Companion.GOOGLE_ACCOUNTS_URL
import zechs.drive.stream.utils.util.Constants.Companion.GOOGLE_API
import zechs.drive.stream.utils.util.Constants.Companion.GOOGLE_OAUTH_URL
import javax.inject.Named
import javax.inject.Singleton

Expand Down Expand Up @@ -133,6 +135,21 @@ object ApiModule {
.create(GithubApi::class.java)
}

@Provides
@Singleton
fun provideRevokeTokenApi(
@Named("OkHttpClient")
client: OkHttpClient,
moshi: Moshi
): RevokeTokenApi {
return Retrofit.Builder()
.baseUrl(GOOGLE_OAUTH_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(RevokeTokenApi::class.java)
}

@Provides
@Singleton
fun provideDriveRepository(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package zechs.drive.stream.ui.add_account

import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.Window
import android.widget.Toast
import com.google.android.material.button.MaterialButton
import com.google.android.material.textfield.TextInputLayout
import zechs.drive.stream.R

class DialogAddAccount(
context: Context,
val onNextClickListener: (String) -> Unit
) : Dialog(context, R.style.ThemeOverlay_Fade_MaterialAlertDialog) {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.dialog_new_account)

val etNickname = findViewById<TextInputLayout>(R.id.tf_nickname).editText!!
val nextButton = findViewById<MaterialButton>(R.id.btn_next)

nextButton.setOnClickListener {
if (etNickname.text.toString().isEmpty()) {
Toast.makeText(
context,
context.getString(R.string.please_enter_a_nickname),
Toast.LENGTH_SHORT
).show()
} else {
onNextClickListener.invoke(etNickname.text.toString())
dismiss()
}
}
}

}
Loading

0 comments on commit 176ecfe

Please sign in to comment.