Move login call to native

pull/653/merge
Varun Patil 2023-10-13 22:04:46 -07:00
parent dbfd56e727
commit 49f97e2895
4 changed files with 55 additions and 81 deletions

View File

@ -41,17 +41,6 @@ div.p {
line-height: 1.5em;
}
p.error {
display: none;
color: red;
font-weight: 500;
word-wrap: break-word;
user-select: text;
background: white;
padding: 10px;
border-radius: 10px;
}
.logo {
color: var(--fg-color);
margin-bottom: 30px;
@ -106,22 +95,3 @@ input.m-input:focus {
margin: 10px;
margin-top: 20px;
}
#folder-list {
margin: 15px;
text-align: left;
}
.folder-choose {
font-size: 1.1em;
margin-top: 4px;
display: grid;
grid-template-columns: 1em auto;
gap: 1.2em;
line-height: 1.8em;
}
input[type="checkbox"] {
width: 2em;
height: 2em;
}

View File

@ -26,8 +26,6 @@
</button>
<br />
<p id="conn-error" class="error"></p>
<a class="m-button link" href="https://memories.gallery/install/">
I don't have a server
</a>
@ -36,7 +34,6 @@
<script>
const urlBox = document.getElementById("server-url");
const loginButton = document.getElementById("login");
const connError = document.getElementById("conn-error");
function validateUrl(url) {
try {
@ -86,10 +83,6 @@
// Login button click handler
loginButton.addEventListener("click", async () => {
const url = getMemoriesUrl();
url.pathname += "api/describe";
const urlStr = url.toString();
try {
urlBox.disabled = true;
loginButton.disabled = true;
@ -98,20 +91,17 @@
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
// Get API description
const res = await fetch(urlStr, {
// Login signal
const encUrl = encodeURIComponent(encodeURIComponent(getMemoriesUrl().toString()));
await fetch(`http://127.0.0.1/api/login/${encUrl}`, {
method: "GET",
signal: controller.signal,
});
const data = await res.json();
// API is fine, redirect to login page
clearTimeout(timeoutId);
window.nativex.login(data.baseUrl, data.loginFlowUrl);
} catch (e) {
// CORS request, we know nothing about the server
connError.innerText = `Failed to fetch server info.\nIs Memories installed and enabled?\n${urlStr}`;
connError.style.display = "block";
// unreachable?
} finally {
urlBox.disabled = false;
loginButton.disabled = false;

View File

@ -43,6 +43,8 @@ class NativeX(private val mCtx: MainActivity) {
}
object API {
val LOGIN = Regex("^/api/login/.+$")
val DAYS = Regex("^/api/days$")
val DAY = Regex("^/api/days/\\d+$")
@ -93,12 +95,6 @@ class NativeX(private val mCtx: MainActivity) {
}
}
@JavascriptInterface
fun login(baseUrl: String?, loginFlowUrl: String?) {
if (baseUrl == null || loginFlowUrl == null) return;
account.login(baseUrl, loginFlowUrl)
}
@JavascriptInterface
fun logout() {
account.loggedOut()
@ -227,7 +223,9 @@ class NativeX(private val mCtx: MainActivity) {
val path = request.url.path ?: return makeErrorResponse()
val parts = path.split("/").toTypedArray()
return if (path.matches(API.DAYS)) {
return if (path.matches(API.LOGIN)) {
makeResponse(account.login(URLDecoder.decode(parts[3], "UTF-8")))
} else if (path.matches(API.DAYS)) {
makeResponse(query.getDays())
} else if (path.matches(API.DAY)) {
makeResponse(query.getDay(parts[3].toLong()))

View File

@ -9,7 +9,6 @@ import androidx.media3.common.util.UnstableApi
import gallery.memories.MainActivity
import gallery.memories.R
import io.github.g00fy2.versioncompare.Version
import java.net.SocketTimeoutException
@UnstableApi
class AccountService(private val mCtx: MainActivity, private val mHttp: HttpService) {
@ -19,42 +18,59 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
private val store = SecureStorage(mCtx)
/**
* Make the first request to log in
* @param url The URL of the Nextcloud server
*/
fun login(url: String) {
try {
Log.v(TAG, "login: Connecting to ${url}api/describe")
mHttp.setBaseUrl(url)
val res = mHttp.getApiDescription()
if (res.code != 200) {
throw Exception("${url}api/describe (status ${res.code})")
}
val body = mHttp.bodyJson(res) ?: throw Exception("Failed to parse API description")
val baseUrl = body.getString("baseUrl")
val loginFlowUrl = body.getString("loginFlowUrl")
loginFlow(baseUrl, loginFlowUrl)
} catch (e: Exception) {
toast("Error: ${e.message}")
throw Exception("Failed to connect to server: ${e.message}")
}
}
/**
* Login to a server
* @param baseUrl The base URL of the server
* @param loginFlowUrl The login flow URL
* @throws Exception If the login flow failed
*/
fun login(baseUrl: String, loginFlowUrl: String) {
try {
val res = mHttp.postLoginFlow(loginFlowUrl)
fun loginFlow(baseUrl: String, loginFlowUrl: String) {
val res = mHttp.postLoginFlow(loginFlowUrl)
// Check if 200 was received
if (res.code != 200) {
throw Exception("Server returned a ${res.code} status code. Please check your reverse proxy configuration and overwriteprotocol is correct.")
}
// Get body as JSON
val body = mHttp.bodyJson(res) ?: throw Exception("Failed to parse login flow response")
// Parse response body as JSON
val pollObj = body.getJSONObject("poll")
val pollToken = pollObj.getString("token")
val pollUrl = pollObj.getString("endpoint")
val loginUrl = body.getString("login")
// Open login page in browser
mCtx.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(loginUrl)))
// Start polling in background
Thread { pollLogin(pollUrl, pollToken, baseUrl) }.start()
} catch (e: SocketTimeoutException) {
toast("Failed to connect to login flow URL")
return
} catch (e: Exception) {
Log.e(TAG, "login: ", e)
toast(e.message ?: "Unknown error")
return
// Check if 200 was received
if (res.code != 200) {
throw Exception("Login flow returned a ${res.code} status code. Check your reverse proxy configuration and overwriteprotocol is correct.")
}
// Get body as JSON
val body = mHttp.bodyJson(res) ?: throw Exception("Failed to parse login flow response")
// Parse response body as JSON
val pollObj = body.getJSONObject("poll")
val pollToken = pollObj.getString("token")
val pollUrl = pollObj.getString("endpoint")
val loginUrl = body.getString("login")
// Open login page in browser
mCtx.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(loginUrl)))
// Start polling in background
Thread { pollLogin(pollUrl, pollToken, baseUrl) }.start()
}
/**