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

View File

@ -43,6 +43,8 @@ class NativeX(private val mCtx: MainActivity) {
} }
object API { object API {
val LOGIN = Regex("^/api/login/.+$")
val DAYS = Regex("^/api/days$") val DAYS = Regex("^/api/days$")
val DAY = Regex("^/api/days/\\d+$") 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 @JavascriptInterface
fun logout() { fun logout() {
account.loggedOut() account.loggedOut()
@ -227,7 +223,9 @@ class NativeX(private val mCtx: MainActivity) {
val path = request.url.path ?: return makeErrorResponse() val path = request.url.path ?: return makeErrorResponse()
val parts = path.split("/").toTypedArray() 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()) makeResponse(query.getDays())
} else if (path.matches(API.DAY)) { } else if (path.matches(API.DAY)) {
makeResponse(query.getDay(parts[3].toLong())) 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.MainActivity
import gallery.memories.R import gallery.memories.R
import io.github.g00fy2.versioncompare.Version import io.github.g00fy2.versioncompare.Version
import java.net.SocketTimeoutException
@UnstableApi @UnstableApi
class AccountService(private val mCtx: MainActivity, private val mHttp: HttpService) { class AccountService(private val mCtx: MainActivity, private val mHttp: HttpService) {
@ -19,18 +18,43 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
private val store = SecureStorage(mCtx) 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 * Login to a server
* @param baseUrl The base URL of the server * @param baseUrl The base URL of the server
* @param loginFlowUrl The login flow URL * @param loginFlowUrl The login flow URL
* @throws Exception If the login flow failed
*/ */
fun login(baseUrl: String, loginFlowUrl: String) { fun loginFlow(baseUrl: String, loginFlowUrl: String) {
try {
val res = mHttp.postLoginFlow(loginFlowUrl) val res = mHttp.postLoginFlow(loginFlowUrl)
// Check if 200 was received // Check if 200 was received
if (res.code != 200) { if (res.code != 200) {
throw Exception("Server returned a ${res.code} status code. Please check your reverse proxy configuration and overwriteprotocol is correct.") throw Exception("Login flow returned a ${res.code} status code. Check your reverse proxy configuration and overwriteprotocol is correct.")
} }
// Get body as JSON // Get body as JSON
@ -47,14 +71,6 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
// Start polling in background // Start polling in background
Thread { pollLogin(pollUrl, pollToken, baseUrl) }.start() 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
}
} }
/** /**