1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-29 12:30:11 +00:00

Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
ae403b7eb8
Merge 7db12fdbe7 into 4f78b7c33b 2023-10-02 07:54:29 -07:00
4f78b7c33b
admin: option link to my account page on login screen 2023-10-02 10:56:50 +01:00
9956bbd974
admin: add setting to hide background on login
for #288.
2023-10-02 10:34:14 +01:00
ff1ea8549a
userpage: register routes on reverse proxy subfolder
fixes #289.
2023-10-02 09:45:42 +01:00
5a2d3d2ee2
admin: My Account button respects URL Base 2023-10-02 09:40:19 +01:00
dependabot[bot]
7db12fdbe7
build(deps): bump word-wrap from 1.2.3 to 1.2.4
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 02:53:03 +00:00
13 changed files with 95 additions and 34 deletions

View File

@ -274,6 +274,18 @@
"value": false, "value": false,
"advanced": true, "advanced": true,
"description": "Navigate directly to the above URL instead of needing the user to click \"Continue\"." "description": "Navigate directly to the above URL instead of needing the user to click \"Continue\"."
},
"login_appearance": {
"name": "Login screen appearance",
"required": false,
"requires_restart": false,
"type": "select",
"options": [
["clear", "Transparent"],
["opaque", "Opaque"]
],
"value": "clear",
"description": "Appearance of the Admin login screen."
} }
} }
}, },
@ -406,6 +418,14 @@
"required": "false", "required": "false",
"description": "Click the edit icon next to the \"User Page\" Setting to add custom Markdown messages that will be shown to the user. Note message cards are not private, little effort is required for anyone to view them." "description": "Click the edit icon next to the \"User Page\" Setting to add custom Markdown messages that will be shown to the user. Note message cards are not private, little effort is required for anyone to view them."
}, },
"show_link": {
"name": "Show Link on Admin Login page",
"required": false,
"requires_restart": false,
"type": "bool",
"value": true,
"description": "Whether or not to show a link to the \"My Account\" page on the admin login screen, to direct lost users."
},
"referrals": { "referrals": {
"name": "User Referrals", "name": "User Referrals",
"required": false, "required": false,

View File

@ -15,6 +15,9 @@
--border-width-4: 5px; --border-width-4: 5px;
--border-width-8: 8px; --border-width-8: 8px;
font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
--bg-light: #fff;
--bg-dark: #101010;
} }
.light { .light {
@ -26,11 +29,11 @@
} }
.dark body { .dark body {
background-color: #101010; background-color: var(--bg-dark);
} }
html:not(.dark) body { html:not(.dark) body {
background-color: #fff; background-color: var(--bg-light);
} }
.dark select, .dark option, .dark input { .dark select, .dark option, .dark input {

View File

@ -10,6 +10,24 @@
background-color: rgba(0,0,0,40%); background-color: rgba(0,0,0,40%);
} }
.wall {
position: fixed;
z-index: 11;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
}
html.dark .wall {
background-color: var(--bg-dark);
}
html:not(.dark) .wall {
background-color: var(--bg-light);
}
.modal-close { .modal-close {
float: right; float: right;
color: #aaa; color: #aaa;

View File

@ -18,6 +18,7 @@
window.jfAdminOnly = {{ .jfAdminOnly }}; window.jfAdminOnly = {{ .jfAdminOnly }};
window.jfAllowAll = {{ .jfAllowAll }}; window.jfAllowAll = {{ .jfAllowAll }};
window.referralsEnabled = {{ .referralsEnabled }}; window.referralsEnabled = {{ .referralsEnabled }};
window.loginAppearance = "{{ .loginAppearance }}";
</script> </script>
<title>Admin - jfa-go</title> <title>Admin - jfa-go</title>
{{ template "header.html" . }} {{ template "header.html" . }}
@ -465,7 +466,7 @@
</div> </div>
{{ if .userPageEnabled }} {{ if .userPageEnabled }}
<div class="top-4 right-4 absolute"> <div class="top-4 right-4 absolute">
<a class="button ~info" href="/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a> <a class="button ~info" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
</div> </div>
{{ end }} {{ end }}
<div class="page-container"> <div class="page-container">

View File

@ -7,6 +7,14 @@
</div> </div>
{{ end }} {{ end }}
{{ end }} {{ end }}
{{ if index . "userPageEnabled" }}
{{ if and .userPageEnabled .showUserPageLink }}
<div class="card mx-2 flex-initial w-[100%] xl:w-[35%] mb-4 xl:mb-0 dark:~d_neutral @low content">
<span class="heading row">{{ .strings.loginNotAdmin }}</span>
<a class="button ~info h-12 w-100" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
</div>
{{ end }}
{{ end }}
<form class="card mx-2 flex-auto form-login w-[100%] xl:w-[55%] mb-0" href=""> <form class="card mx-2 flex-auto form-login w-[100%] xl:w-[55%] mb-0" href="">
<span class="heading">{{ .strings.login }}</span> <span class="heading">{{ .strings.login }}</span>
<input type="text" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.username }}" id="login-user"> <input type="text" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.username }}" id="login-user">

View File

@ -123,7 +123,8 @@
"userPageLogin": "User Page: Login", "userPageLogin": "User Page: Login",
"userPagePage": "User Page: Page", "userPagePage": "User Page: Page",
"buildTime": "Build Time", "buildTime": "Build Time",
"builtBy": "Built By" "builtBy": "Built By",
"loginNotAdmin": "Not an Admin?"
}, },
"notifications": { "notifications": {
"changedEmailAddress": "Changed email address of {n}.", "changedEmailAddress": "Changed email address of {n}.",

12
package-lock.json generated
View File

@ -6677,9 +6677,9 @@
} }
}, },
"node_modules/word-wrap": { "node_modules/word-wrap": {
"version": "1.2.3", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -11812,9 +11812,9 @@
} }
}, },
"word-wrap": { "word-wrap": {
"version": "1.2.3", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA=="
}, },
"wrap-ansi": { "wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",

View File

@ -160,12 +160,11 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
api := router.Group("/", app.webAuth()) api := router.Group("/", app.webAuth())
for _, p := range routePrefixes {
var user *gin.RouterGroup var user *gin.RouterGroup
if userPageEnabled { if userPageEnabled {
user = router.Group("/my", app.userAuth()) user = router.Group(p+"/my", app.userAuth())
} }
for _, p := range routePrefixes {
router.POST(p+"/logout", app.Logout) router.POST(p+"/logout", app.Logout)
api.DELETE(p+"/users", app.DeleteUsers) api.DELETE(p+"/users", app.DeleteUsers)
api.GET(p+"/users", app.GetUsers) api.GET(p+"/users", app.GetUsers)
@ -234,22 +233,22 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
} }
if userPageEnabled { if userPageEnabled {
user.GET(p+"/details", app.MyDetails) user.GET("/details", app.MyDetails)
user.POST(p+"/contact", app.SetMyContactMethods) user.POST("/contact", app.SetMyContactMethods)
user.POST(p+"/logout", app.LogoutUser) user.POST("/logout", app.LogoutUser)
user.POST(p+"/email", app.ModifyMyEmail) user.POST("/email", app.ModifyMyEmail)
user.GET(p+"/discord/invite", app.MyDiscordServerInvite) user.GET("/discord/invite", app.MyDiscordServerInvite)
user.GET(p+"/pin/:service", app.GetMyPIN) user.GET("/pin/:service", app.GetMyPIN)
user.GET(p+"/discord/verified/:pin", app.MyDiscordVerifiedInvite) user.GET("/discord/verified/:pin", app.MyDiscordVerifiedInvite)
user.GET(p+"/telegram/verified/:pin", app.MyTelegramVerifiedInvite) user.GET("/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
user.POST(p+"/matrix/user", app.MatrixSendMyPIN) user.POST("/matrix/user", app.MatrixSendMyPIN)
user.GET(p+"/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN) user.GET("/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN)
user.DELETE(p+"/discord", app.UnlinkMyDiscord) user.DELETE("/discord", app.UnlinkMyDiscord)
user.DELETE(p+"/telegram", app.UnlinkMyTelegram) user.DELETE("/telegram", app.UnlinkMyTelegram)
user.DELETE(p+"/matrix", app.UnlinkMyMatrix) user.DELETE("/matrix", app.UnlinkMyMatrix)
user.POST(p+"/password", app.ChangeMyPassword) user.POST("/password", app.ChangeMyPassword)
if app.config.Section("user_page").Key("referrals").MustBool(false) { if app.config.Section("user_page").Key("referrals").MustBool(false) {
user.GET(p+"/referral", app.GetMyReferral) user.GET("/referral", app.GetMyReferral)
} }
} }
} }

View File

@ -163,7 +163,7 @@ window.onpopstate = (event: PopStateEvent) => {
window.tabs.switch(event.state); window.tabs.switch(event.state);
} }
const login = new Login(window.modals.login as Modal, "/"); const login = new Login(window.modals.login as Modal, "/", window.loginAppearance);
login.onLogin = () => { login.onLogin = () => {
console.log("Logged in."); console.log("Logged in.");
window.updater = new Updater(); window.updater = new Updater();

View File

@ -8,13 +8,21 @@ export class Login {
private _endpoint: string; private _endpoint: string;
private _onLogin: (username: string, password: string) => void; private _onLogin: (username: string, password: string) => void;
private _logoutButton: HTMLElement = null; private _logoutButton: HTMLElement = null;
private _wall: HTMLElement;
private _hasOpacityWall: boolean = false;
constructor(modal: Modal, endpoint: string) { constructor(modal: Modal, endpoint: string, appearance: string) {
this._endpoint = endpoint; this._endpoint = endpoint;
this._url = window.URLBase + endpoint; this._url = window.URLBase + endpoint;
if (this._url[this._url.length-1] != '/') this._url += "/"; if (this._url[this._url.length-1] != '/') this._url += "/";
this._modal = modal; this._modal = modal;
if (appearance == "opaque") {
this._hasOpacityWall = true;
this._wall = document.createElement("div");
this._wall.classList.add("wall");
this._modal.asElement().parentElement.appendChild(this._wall);
}
this._form = this._modal.asElement().querySelector(".form-login") as HTMLFormElement; this._form = this._modal.asElement().querySelector(".form-login") as HTMLFormElement;
this._form.onsubmit = (event: SubmitEvent) => { this._form.onsubmit = (event: SubmitEvent) => {
event.preventDefault(); event.preventDefault();
@ -86,6 +94,7 @@ export class Login {
if (this._onLogin) { if (this._onLogin) {
this._onLogin(username, password); this._onLogin(username, password);
} }
if (this._hasOpacityWall) this._wall.remove();
this._modal.close(); this._modal.close();
if (this._logoutButton != null) if (this._logoutButton != null)
this._logoutButton.classList.remove("unfocused"); this._logoutButton.classList.remove("unfocused");

View File

@ -41,6 +41,7 @@ declare interface Window {
jfAdminOnly: boolean; jfAdminOnly: boolean;
jfAllowAll: boolean; jfAllowAll: boolean;
referralsEnabled: boolean; referralsEnabled: boolean;
loginAppearance: string;
} }
declare interface Update { declare interface Update {

View File

@ -556,7 +556,6 @@ changePasswordButton.addEventListener("click", () => {
} }
}); });
}); });
// FIXME: Submit & Validate
document.addEventListener("details-reload", () => { document.addEventListener("details-reload", () => {
_get("/my/details", null, (req: XMLHttpRequest) => { _get("/my/details", null, (req: XMLHttpRequest) => {
@ -645,7 +644,7 @@ document.addEventListener("details-reload", () => {
}); });
}); });
const login = new Login(window.modals.login as Modal, "/my/"); const login = new Login(window.modals.login as Modal, "/my/", "opaque");
login.onLogin = () => { login.onLogin = () => {
console.log("Logged in."); console.log("Logged in.");
document.querySelector(".page-container").classList.remove("unfocused"); document.querySelector(".page-container").classList.remove("unfocused");

View File

@ -175,7 +175,9 @@ func (app *appContext) AdminPage(gc *gin.Context) {
"jfAdminOnly": jfAdminOnly, "jfAdminOnly": jfAdminOnly,
"jfAllowAll": jfAllowAll, "jfAllowAll": jfAllowAll,
"userPageEnabled": app.config.Section("user_page").Key("enabled").MustBool(false), "userPageEnabled": app.config.Section("user_page").Key("enabled").MustBool(false),
"showUserPageLink": app.config.Section("user_page").Key("show_link").MustBool(true),
"referralsEnabled": app.config.Section("user_page").Key("enabled").MustBool(false) && app.config.Section("user_page").Key("referrals").MustBool(false), "referralsEnabled": app.config.Section("user_page").Key("enabled").MustBool(false) && app.config.Section("user_page").Key("referrals").MustBool(false),
"loginAppearance": app.config.Section("ui").Key("login_appearance").MustString("clear"),
}) })
} }