Skip to content

Commit c6ce532

Browse files
committed
Added LFS credentials caching
1 parent 12c4b5a commit c6ce532

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

src/main/kotlin/com/jetpackduba/gitnuro/credentials/CredentialsCacheRepository.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ class CredentialsCacheRepository @Inject constructor() {
2020
// having a random key to encrypt the password may help in case of a memory dump attack
2121
private val encryptionKey = getRandomKey()
2222

23-
fun getCachedHttpCredentials(url: String): CredentialsType.HttpCredentials? {
23+
fun getCachedHttpCredentials(url: String, isLfs: Boolean): CredentialsType.HttpCredentials? {
2424
val credentials = credentialsCached.filterIsInstance<CredentialsType.HttpCredentials>().firstOrNull {
25-
it.url == url
25+
it.url == url && it.isLfs == isLfs
2626
}
2727

2828
return credentials?.copy(password = credentials.password.cipherDecrypt())
2929
}
3030

3131
suspend fun cacheHttpCredentials(credentials: CredentialsType.HttpCredentials) {
32-
cacheHttpCredentials(credentials.url, credentials.userName, credentials.password)
32+
cacheHttpCredentials(credentials.url, credentials.userName, credentials.password, credentials.isLfs)
3333
}
3434

35-
suspend fun cacheHttpCredentials(url: String, userName: String, password: String) {
35+
suspend fun cacheHttpCredentials(url: String, userName: String, password: String, isLfs: Boolean) {
3636
val passwordEncrypted = password.cipherEncrypt()
3737

3838
credentialsLock.lockUse {
@@ -41,7 +41,7 @@ class CredentialsCacheRepository @Inject constructor() {
4141
}
4242

4343
if (!previouslyCached) {
44-
val credentials = CredentialsType.HttpCredentials(url, userName, passwordEncrypted)
44+
val credentials = CredentialsType.HttpCredentials(url, userName, passwordEncrypted, isLfs)
4545
credentialsCached.add(credentials)
4646
}
4747
}
@@ -101,5 +101,6 @@ sealed interface CredentialsType {
101101
val url: String,
102102
val userName: String,
103103
val password: String,
104+
val isLfs: Boolean,
104105
) : CredentialsType
105106
}

src/main/kotlin/com/jetpackduba/gitnuro/credentials/HttpCredentialsProvider.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ class HttpCredentialsProvider @AssistedInject constructor(
7878
val externalCredentialsHelper = getExternalCredentialsHelper(uri, git)
7979

8080
if (externalCredentialsHelper == null) {
81-
val cachedCredentials = credentialsCacheRepository.getCachedHttpCredentials(uri.toString())
81+
val cachedCredentials = credentialsCacheRepository.getCachedHttpCredentials(
82+
url = uri.toString(),
83+
isLfs = false,
84+
)
8285

8386
if (cachedCredentials == null) {
8487
val credentials = askForCredentials()
@@ -92,6 +95,7 @@ class HttpCredentialsProvider @AssistedInject constructor(
9295
url = uri.toString(),
9396
userName = credentials.user,
9497
password = credentials.password,
98+
isLfs = false,
9599
)
96100
}
97101

src/main/kotlin/com/jetpackduba/gitnuro/lfs/GLfsFactory.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.jetpackduba.gitnuro.lfs
22

33
import com.jetpackduba.gitnuro.Result
44
import com.jetpackduba.gitnuro.credentials.CredentialsAccepted
5+
import com.jetpackduba.gitnuro.credentials.CredentialsCacheRepository
56
import com.jetpackduba.gitnuro.credentials.CredentialsRequest
67
import com.jetpackduba.gitnuro.credentials.CredentialsStateManager
78
import com.jetpackduba.gitnuro.logging.printLog
@@ -41,10 +42,18 @@ private const val TAG = "GLfsFactory"
4142
class GLfsFactory @Inject constructor(
4243
private val lfsRepository: LfsRepository,
4344
private val credentialsStateManager: CredentialsStateManager,
45+
private val credentialsCacheRepository: CredentialsCacheRepository,
4446
) : LfsFactory() {
4547
init {
4648
FilterCommandRegistry.register("jgit://builtin/lfs/smudge") { repository, input, out ->
47-
LfsSmudgeFilter(lfsRepository, credentialsStateManager, input, out, repository)
49+
LfsSmudgeFilter(
50+
lfsRepository = lfsRepository,
51+
credentialsStateManager = credentialsStateManager,
52+
credentialsCacheRepository = credentialsCacheRepository,
53+
input = input,
54+
output = out,
55+
repository = repository
56+
)
4857
}
4958
FilterCommandRegistry.register("jgit://builtin/lfs/clean") { db, `in`, out ->
5059
LfsCleanFilter(db, `in`, out)

src/main/kotlin/com/jetpackduba/gitnuro/lfs/LfsSmudgeFilter.kt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.jetpackduba.gitnuro.lfs
22

33
import com.jetpackduba.gitnuro.Result
44
import com.jetpackduba.gitnuro.credentials.CredentialsAccepted
5+
import com.jetpackduba.gitnuro.credentials.CredentialsCacheRepository
56
import com.jetpackduba.gitnuro.credentials.CredentialsRequest
67
import com.jetpackduba.gitnuro.credentials.CredentialsStateManager
78
import com.jetpackduba.gitnuro.logging.printLog
@@ -16,6 +17,7 @@ import org.eclipse.jgit.lfs.LfsPointer
1617
import org.eclipse.jgit.lfs.lib.AnyLongObjectId
1718
import org.eclipse.jgit.lib.Repository
1819
import java.io.*
20+
import java.net.URI
1921
import java.nio.file.Files
2022
import java.util.concurrent.CancellationException
2123

@@ -24,6 +26,7 @@ private const val MAX_COPY_BYTES = 1024 * 1024 * 256
2426
class LfsSmudgeFilter(
2527
private val lfsRepository: LfsRepository,
2628
private val credentialsStateManager: CredentialsStateManager,
29+
private val credentialsCacheRepository: CredentialsCacheRepository,
2730
input: InputStream,
2831
output: OutputStream,
2932
repository: Repository,
@@ -57,6 +60,7 @@ class LfsSmudgeFilter(
5760
res: LfsPointer,
5861
) = runBlocking {
5962
val lfsServerUrl = lfsRepository.getLfsRepositoryUrl(repository)
63+
6064
val hash = res.oid.name()
6165
val size = res.size
6266

@@ -67,17 +71,44 @@ class LfsSmudgeFilter(
6771
)
6872

6973
var credentials: CredentialsAccepted.LfsCredentialsAccepted? = null
74+
var cachedCredentialsAlreadyRequested = false
7075

7176
val lfsObjects = getLfsObjects(lfsServerUrl, lfsPrepareUploadObjectBatch) {
77+
if (!cachedCredentialsAlreadyRequested) {
78+
val cachedCredentials = credentialsCacheRepository.getCachedHttpCredentials(lfsServerUrl, true)
79+
80+
if (cachedCredentials != null) {
81+
val newCredentials = CredentialsAccepted.LfsCredentialsAccepted(
82+
user = cachedCredentials.userName,
83+
password = cachedCredentials.password,
84+
)
85+
86+
credentials = newCredentials
87+
88+
cachedCredentialsAlreadyRequested = true
89+
90+
return@getLfsObjects newCredentials
91+
}
92+
}
93+
7294
val newCredentials = requestLfsCredentials()
7395
credentials = newCredentials
7496

75-
newCredentials
97+
return@getLfsObjects newCredentials
7698
}
7799

78100
when (lfsObjects) {
79101
is Result.Err -> throw Exception("LFS Error ${lfsObjects.error}")
80102
is Result.Ok -> {
103+
credentials?.let { safeCredentials ->
104+
credentialsCacheRepository.cacheHttpCredentials(
105+
lfsServerUrl,
106+
safeCredentials.user,
107+
safeCredentials.password,
108+
isLfs = true,
109+
)
110+
}
111+
81112
val lfs = Lfs(repository)
82113

83114
printLog("LFS", "Requesting credentials for objects upload")

0 commit comments

Comments
 (0)