mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-10-08 21:52:45 +02:00
Allows login with NIP-05 address
This commit is contained in:
@@ -25,12 +25,9 @@ import com.vitorpamplona.amethyst.BuildConfig
|
|||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.Call
|
|
||||||
import okhttp3.Callback
|
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
|
||||||
|
|
||||||
class Nip05NostrAddressVerifier() {
|
class Nip05NostrAddressVerifier {
|
||||||
fun assembleUrl(nip05address: String): String? {
|
fun assembleUrl(nip05address: String): String? {
|
||||||
val parts = nip05address.trim().split("@")
|
val parts = nip05address.trim().split("@")
|
||||||
|
|
||||||
@@ -46,7 +43,7 @@ class Nip05NostrAddressVerifier() {
|
|||||||
|
|
||||||
suspend fun fetchNip05Json(
|
suspend fun fetchNip05Json(
|
||||||
nip05: String,
|
nip05: String,
|
||||||
onSuccess: (String) -> Unit,
|
onSuccess: suspend (String) -> Unit,
|
||||||
onError: (String) -> Unit,
|
onError: (String) -> Unit,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(Dispatchers.IO) {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
@@ -60,52 +57,39 @@ class Nip05NostrAddressVerifier() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val request =
|
val request =
|
||||||
Request.Builder()
|
Request
|
||||||
|
.Builder()
|
||||||
.header("User-Agent", "Amethyst/${BuildConfig.VERSION_NAME}")
|
.header("User-Agent", "Amethyst/${BuildConfig.VERSION_NAME}")
|
||||||
.url(url)
|
.url(url)
|
||||||
.build()
|
.build()
|
||||||
// Fetchers MUST ignore any HTTP redirects given by the /.well-known/nostr.json endpoint.
|
// Fetchers MUST ignore any HTTP redirects given by the /.well-known/nostr.json endpoint.
|
||||||
HttpClientManager.getHttpClient().newBuilder().followRedirects(false).build()
|
HttpClientManager
|
||||||
|
.getHttpClient()
|
||||||
|
.newBuilder()
|
||||||
|
.followRedirects(false)
|
||||||
|
.build()
|
||||||
.newCall(request)
|
.newCall(request)
|
||||||
.enqueue(
|
.execute()
|
||||||
object : Callback {
|
.use {
|
||||||
override fun onResponse(
|
checkNotInMainThread()
|
||||||
call: Call,
|
|
||||||
response: Response,
|
|
||||||
) {
|
|
||||||
checkNotInMainThread()
|
|
||||||
|
|
||||||
response.use {
|
if (it.isSuccessful) {
|
||||||
if (it.isSuccessful) {
|
onSuccess(it.body.string())
|
||||||
onSuccess(it.body.string())
|
} else {
|
||||||
} else {
|
onError(
|
||||||
onError(
|
"Could not resolve $nip05. Error: ${it.code}. Check if the server is up and if the address $nip05 is correct",
|
||||||
"Could not resolve $nip05. Error: ${it.code}. Check if the server is up and if the address $nip05 is correct",
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(
|
|
||||||
call: Call,
|
|
||||||
e: java.io.IOException,
|
|
||||||
) {
|
|
||||||
onError(
|
|
||||||
"Could not resolve $url. Check if the server is up and if the address $nip05 is correct",
|
|
||||||
)
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (e is CancellationException) throw e
|
if (e is CancellationException) throw e
|
||||||
onError("Could not resolve '$url': ${e.message}")
|
onError("Could not resolve NIP-05 $nip05 as URL $url: ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun verifyNip05(
|
suspend fun verifyNip05(
|
||||||
nip05: String,
|
nip05: String,
|
||||||
onSuccess: (String) -> Unit,
|
onSuccess: suspend (String) -> Unit,
|
||||||
onError: (String) -> Unit,
|
onError: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
// check fails on tests
|
// check fails on tests
|
||||||
|
@@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.LocalPreferences
|
|||||||
import com.vitorpamplona.amethyst.ServiceManager
|
import com.vitorpamplona.amethyst.ServiceManager
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.service.HttpClientManager
|
import com.vitorpamplona.amethyst.service.HttpClientManager
|
||||||
|
import com.vitorpamplona.amethyst.service.Nip05NostrAddressVerifier
|
||||||
import com.vitorpamplona.amethyst.service.relays.Client
|
import com.vitorpamplona.amethyst.service.relays.Client
|
||||||
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
||||||
import com.vitorpamplona.quartz.crypto.KeyPair
|
import com.vitorpamplona.quartz.crypto.KeyPair
|
||||||
@@ -57,7 +58,7 @@ import java.util.regex.Pattern
|
|||||||
val EMAIL_PATTERN = Pattern.compile(".+@.+\\.[a-z]+")
|
val EMAIL_PATTERN = Pattern.compile(".+@.+\\.[a-z]+")
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
class AccountStateViewModel() : ViewModel() {
|
class AccountStateViewModel : ViewModel() {
|
||||||
var serviceManager: ServiceManager? = null
|
var serviceManager: ServiceManager? = null
|
||||||
|
|
||||||
private val _accountContent = MutableStateFlow<AccountState>(AccountState.Loading)
|
private val _accountContent = MutableStateFlow<AccountState>(AccountState.Loading)
|
||||||
@@ -144,15 +145,6 @@ class AccountStateViewModel() : ViewModel() {
|
|||||||
proxyPort = proxyPort,
|
proxyPort = proxyPort,
|
||||||
signer = NostrSignerInternal(keyPair),
|
signer = NostrSignerInternal(keyPair),
|
||||||
)
|
)
|
||||||
} else if (EMAIL_PATTERN.matcher(key).matches()) {
|
|
||||||
val keyPair = KeyPair()
|
|
||||||
// TODO: Evaluate NIP-5
|
|
||||||
Account(
|
|
||||||
keyPair,
|
|
||||||
proxy = proxy,
|
|
||||||
proxyPort = proxyPort,
|
|
||||||
signer = NostrSignerInternal(keyPair),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
val keyPair = KeyPair(Hex.decode(key))
|
val keyPair = KeyPair(Hex.decode(key))
|
||||||
Account(
|
Account(
|
||||||
@@ -243,6 +235,18 @@ class AccountStateViewModel() : ViewModel() {
|
|||||||
onError(null)
|
onError(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (EMAIL_PATTERN.matcher(key).matches()) {
|
||||||
|
Nip05NostrAddressVerifier().verifyNip05(
|
||||||
|
key,
|
||||||
|
onSuccess = { publicKey ->
|
||||||
|
loginSync(Hex.decode(publicKey).toNpub(), useProxy, proxyPort, loginWithExternalSigner, packageName) {
|
||||||
|
onError(null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError = {
|
||||||
|
onError(it)
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
loginSync(key, useProxy, proxyPort, loginWithExternalSigner, packageName) {
|
loginSync(key, useProxy, proxyPort, loginWithExternalSigner, packageName) {
|
||||||
onError(null)
|
onError(null)
|
||||||
|
Reference in New Issue
Block a user