forked from go-shiori/shiori
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move login.html into a login component (go-shiori#1017)
* feat: Add login component JavaScript file * feat: Create login component and refactor login view * refactor: Convert login to single-page application with dynamic component rendering * feat: Enhance session validation and login form display logic * fix: Resolve Vue app mounting and method duplication issues * fix: Prevent null reference error when focusing username input * fix: Initialize `isLoggedIn` to true to show login form during async check * refactor: Improve session validation and login flow logic * fix: Adjust login component visibility and initial login state * feat: Add login form template to login component * feat: Update login template to match original login.html design * fix: Resolve login view rendering and state management issues * refactor: Remove login route from frontend routes * refactor: Remove login-footer from login component template * fix: Modify logout to show login form without redirecting * refactor: Remove /login route test for SPA architecture * refactor: delete login.html file * style: Remove extra blank line in frontend_test.go * chore: run make style changes
- Loading branch information
Showing
5 changed files
with
217 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
const template = ` | ||
<div id="login-scene"> | ||
<p class="error-message" v-if="error !== ''">{{error}}</p> | ||
<div id="login-box"> | ||
<form @submit.prevent="login"> | ||
<div id="logo-area"> | ||
<p id="logo"> | ||
<span>栞</span>shiori | ||
</p> | ||
<p id="tagline">simple bookmark manager</p> | ||
</div> | ||
<div id="input-area"> | ||
<label for="username">Username: </label> | ||
<input id="username" type="text" name="username" placeholder="Username" tabindex="1" autofocus /> | ||
<label for="password">Password: </label> | ||
<input id="password" type="password" name="password" placeholder="Password" tabindex="2" | ||
@keyup.enter="login"> | ||
<label class="checkbox-field"><input type="checkbox" name="remember" v-model="remember" | ||
tabindex="3">Remember me</label> | ||
</div> | ||
<div id="button-area"> | ||
<a v-if="loading"> | ||
<i class="fas fa-fw fa-spinner fa-spin"></i> | ||
</a> | ||
<a v-else class="button" tabindex="4" @click="login" @keyup.enter="login">Log In</a> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
`; | ||
|
||
export default { | ||
name: "login-view", | ||
template, | ||
data() { | ||
return { | ||
error: "", | ||
loading: false, | ||
username: "", | ||
password: "", | ||
remember: false, | ||
}; | ||
}, | ||
emits: ["login-success"], | ||
methods: { | ||
async getErrorMessage(err) { | ||
switch (err.constructor) { | ||
case Error: | ||
return err.message; | ||
case Response: | ||
var text = await err.text(); | ||
|
||
// Handle new error messages | ||
if (text[0] == "{") { | ||
var json = JSON.parse(text); | ||
return json.message; | ||
} | ||
return `${text} (${err.status})`; | ||
default: | ||
return err; | ||
} | ||
}, | ||
parseJWT(token) { | ||
try { | ||
return JSON.parse(atob(token.split(".")[1])); | ||
} catch (e) { | ||
return null; | ||
} | ||
}, | ||
login() { | ||
// Get values directly from the form | ||
const usernameInput = document.querySelector("#username"); | ||
const passwordInput = document.querySelector("#password"); | ||
this.username = usernameInput ? usernameInput.value : this.username; | ||
this.password = passwordInput ? passwordInput.value : this.password; | ||
|
||
// Validate input | ||
if (this.username === "") { | ||
this.error = "Username must not empty"; | ||
return; | ||
} | ||
|
||
// Remove old cookie | ||
document.cookie = `session-id=; Path=${ | ||
new URL(document.baseURI).pathname | ||
}; Expires=Thu, 01 Jan 1970 00:00:00 GMT;`; | ||
|
||
// Send request | ||
this.loading = true; | ||
|
||
fetch(new URL("api/v1/auth/login", document.baseURI), { | ||
method: "post", | ||
body: JSON.stringify({ | ||
username: this.username, | ||
password: this.password, | ||
remember_me: this.remember == 1 ? true : false, | ||
}), | ||
headers: { "Content-Type": "application/json" }, | ||
}) | ||
.then((response) => { | ||
if (!response.ok) throw response; | ||
return response.json(); | ||
}) | ||
.then((json) => { | ||
// Save session id | ||
document.cookie = `session-id=${json.message.session}; Path=${ | ||
new URL(document.baseURI).pathname | ||
}; Expires=${json.message.expires}`; | ||
document.cookie = `token=${json.message.token}; Path=${ | ||
new URL(document.baseURI).pathname | ||
}; Expires=${json.message.expires}`; | ||
|
||
// Save account data | ||
localStorage.setItem("shiori-token", json.message.token); | ||
localStorage.setItem( | ||
"shiori-account", | ||
JSON.stringify(this.parseJWT(json.message.token).account), | ||
); | ||
|
||
this.visible = false; | ||
this.$emit("login-success"); | ||
}) | ||
.catch((err) => { | ||
this.loading = false; | ||
this.getErrorMessage(err).then((msg) => { | ||
this.error = msg; | ||
}); | ||
}); | ||
}, | ||
}, | ||
mounted() { | ||
// Clear any existing cookies | ||
document.cookie = `session-id=; Path=${ | ||
new URL(document.baseURI).pathname | ||
}; Expires=Thu, 01 Jan 1970 00:00:00 GMT;`; | ||
document.cookie = `token=; Path=${ | ||
new URL(document.baseURI).pathname | ||
}; Expires=Thu, 01 Jan 1970 00:00:00 GMT;`; | ||
|
||
// Clear local storage | ||
localStorage.removeItem("shiori-account"); | ||
localStorage.removeItem("shiori-token"); | ||
|
||
// <input autofocus> wasn't working all the time, so I'm putting this here as a fallback | ||
this.$nextTick(() => { | ||
const usernameInput = document.querySelector("#username"); | ||
if (usernameInput) { | ||
usernameInput.focus(); | ||
} | ||
}); | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.