1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 09:00:10 +00:00

userpage: initial page

login, lang, and theme work. Currently only makes a request to a
hello-world type endpoint to verify auth works. Accessible at
/my/account.
This commit is contained in:
Harvey Tindall 2023-06-16 14:43:37 +01:00
parent 54fde33a20
commit 726acb9c29
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
13 changed files with 225 additions and 55 deletions

View File

@ -104,6 +104,7 @@ typescript:
$(info compiling typescript) $(info compiling typescript)
mkdir -p $(DATA)/web/js mkdir -p $(DATA)/web/js
$(ESBUILD) --target=es6 --bundle tempts/admin.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/admin.js --minify $(ESBUILD) --target=es6 --bundle tempts/admin.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/admin.js --minify
$(ESBUILD) --target=es6 --bundle tempts/user.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/user.js --minify
$(ESBUILD) --target=es6 --bundle tempts/pwr.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/pwr.js --minify $(ESBUILD) --target=es6 --bundle tempts/pwr.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/pwr.js --minify
$(ESBUILD) --target=es6 --bundle tempts/form.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/form.js --minify $(ESBUILD) --target=es6 --bundle tempts/form.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/form.js --minify
$(ESBUILD) --target=es6 --bundle tempts/setup.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/setup.js --minify $(ESBUILD) --target=es6 --bundle tempts/setup.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/setup.js --minify

7
api-userpage.go Normal file
View File

@ -0,0 +1,7 @@
package main
import "github.com/gin-gonic/gin"
func (app *appContext) HelloWorld(gc *gin.Context) {
gc.JSON(200, stringResponse{"It worked!", "none"})
}

10
api.go
View File

@ -214,7 +214,7 @@ func (app *appContext) GetConfig(gc *gin.Context) {
app.info.Println("Config requested") app.info.Println("Config requested")
resp := app.configBase resp := app.configBase
// Load language options // Load language options
formOptions := app.storage.lang.Form.getOptions() formOptions := app.storage.lang.User.getOptions()
fl := resp.Sections["ui"].Settings["language-form"] fl := resp.Sections["ui"].Settings["language-form"]
fl.Options = formOptions fl.Options = formOptions
fl.Value = app.config.Section("ui").Key("language-form").MustString("en-us") fl.Value = app.config.Section("ui").Key("language-form").MustString("en-us")
@ -452,8 +452,8 @@ func (app *appContext) GetLanguages(gc *gin.Context) {
page := gc.Param("page") page := gc.Param("page")
resp := langDTO{} resp := langDTO{}
switch page { switch page {
case "form": case "form", "user":
for key, lang := range app.storage.lang.Form { for key, lang := range app.storage.lang.User {
resp[key] = lang.Meta.Name resp[key] = lang.Meta.Name
} }
case "admin": case "admin":
@ -494,8 +494,8 @@ func (app *appContext) ServeLang(gc *gin.Context) {
if page == "admin" { if page == "admin" {
gc.JSON(200, app.storage.lang.Admin[lang]) gc.JSON(200, app.storage.lang.Admin[lang])
return return
} else if page == "form" { } else if page == "form" || page == "user" {
gc.JSON(200, app.storage.lang.Form[lang]) gc.JSON(200, app.storage.lang.User[lang])
return return
} }
respondBool(400, false, gc) respondBool(400, false, gc)

View File

@ -169,11 +169,11 @@ func (app *appContext) loadConfig() error {
oldFormLang := app.config.Section("ui").Key("language").MustString("") oldFormLang := app.config.Section("ui").Key("language").MustString("")
if oldFormLang != "" { if oldFormLang != "" {
app.storage.lang.chosenFormLang = oldFormLang app.storage.lang.chosenUserLang = oldFormLang
} }
newFormLang := app.config.Section("ui").Key("language-form").MustString("") newFormLang := app.config.Section("ui").Key("language-form").MustString("")
if newFormLang != "" { if newFormLang != "" {
app.storage.lang.chosenFormLang = newFormLang app.storage.lang.chosenUserLang = newFormLang
} }
app.storage.lang.chosenAdminLang = app.config.Section("ui").Key("language-admin").MustString("en-us") app.storage.lang.chosenAdminLang = app.config.Section("ui").Key("language-admin").MustString("en-us")
app.storage.lang.chosenEmailLang = app.config.Section("email").Key("language").MustString("en-us") app.storage.lang.chosenEmailLang = app.config.Section("email").Key("language").MustString("en-us")

View File

@ -373,6 +373,23 @@
} }
} }
}, },
"user_page": {
"order": [],
"meta": {
"name": "User Page",
"description": "Settings for the user page, which provides useful info and tools to users directly. NOTE: Jellyfin Login must be enabled to use this feature.",
"depends_true": "ui|jellyfin_login"
},
"settings": {
"enabled": {
"name": "Enabled",
"required": false,
"requires_restart": false,
"type": "bool",
"value": true
}
}
},
"password_validation": { "password_validation": {
"order": [], "order": [],
"meta": { "meta": {

53
html/user.html Normal file
View File

@ -0,0 +1,53 @@
<html lang="en" class="light">
<head>
<link rel="stylesheet" type="text/css" href="{{ .urlBase }}/css/{{ .cssVersion }}bundle.css">
<script>
window.URLBase = "{{ .urlBase }}";
window.notificationsEnabled = {{ .notifications }};
window.emailEnabled = {{ .emailEnabled }};
window.telegramEnabled = {{ .telegramEnabled }};
window.discordEnabled = {{ .discordEnabled }};
window.matrixEnabled = {{ .matrixEnabled }};
window.ombiEnabled = {{ .ombiEnabled }};
window.langFile = JSON.parse({{ .language }});
window.linkResetEnabled = {{ .linkResetEnabled }};
window.language = "{{ .langName }}";
</script>
{{ template "header.html" . }}
<title>{{ .lang.Strings.pageTitle }}</title>
</head>
<body class="max-w-full overflow-x-hidden section">
<div id="notification-box"></div>
<div class="top-4 left-4 absolute">
<span class="dropdown" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
<i class="ri-global-line"></i>
<span class="ml-2 chev"></span>
</span>
<div class="dropdown-display">
<div class="card ~neutral @low">
<label class="switch pb-4">
<input type="radio" name="lang-time" id="lang-12h">
<span>{{ .strings.time12h }}</span>
</label>
<label class="switch pb-4">
<input type="radio" name="lang-time" id="lang-24h">
<span>{{ .strings.time24h }}</span>
</label>
<div id="lang-list"></div>
</div>
</div>
</span>
<span class="button ~warning" alt="{{ .strings.theme }}" id="button-theme"><i class="ri-sun-line"></i></span>
<span class="button ~critical @low mb-4 unfocused" id="logout-button">{{ .strings.logout }}</span>
</div>
{{ template "login-modal.html" . }}
<div class="page-container">
<div class="card @low dark:~d_neutral mb-4" id="card-user">
Not logged in.
</div>
</div>
<script src="{{ .urlBase }}/js/user.js" type="module"></script>
</body>
</html>

View File

@ -38,9 +38,9 @@ type adminLang struct {
JSON string JSON string
} }
type formLangs map[string]formLang type userLangs map[string]userLang
func (ls *formLangs) getOptions() [][2]string { func (ls *userLangs) getOptions() [][2]string {
opts := make([][2]string, len(*ls)) opts := make([][2]string, len(*ls))
i := 0 i := 0
for key, lang := range *ls { for key, lang := range *ls {
@ -50,7 +50,7 @@ func (ls *formLangs) getOptions() [][2]string {
return opts return opts
} }
type formLang struct { type userLang struct {
Meta langMeta `json:"meta"` Meta langMeta `json:"meta"`
Strings langSection `json:"strings"` Strings langSection `json:"strings"`
Notifications langSection `json:"notifications"` Notifications langSection `json:"notifications"`

View File

@ -284,7 +284,7 @@ func start(asDaemon, firstCall bool) {
} }
app.storage.lang.CommonPath = "common" app.storage.lang.CommonPath = "common"
app.storage.lang.FormPath = "form" app.storage.lang.UserPath = "form"
app.storage.lang.AdminPath = "admin" app.storage.lang.AdminPath = "admin"
app.storage.lang.EmailPath = "email" app.storage.lang.EmailPath = "email"
app.storage.lang.TelegramPath = "telegram" app.storage.lang.TelegramPath = "telegram"

View File

@ -101,6 +101,9 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
if app.URLBase != "" { if app.URLBase != "" {
routePrefixes = append(routePrefixes, "") routePrefixes = append(routePrefixes, "")
} }
userPageEnabled := app.config.Section("user_page").Key("enabled").MustBool(true) && app.config.Section("ui").Key("jellyfin_login").MustBool(true)
for _, p := range routePrefixes { for _, p := range routePrefixes {
router.GET(p+"/lang/:page", app.GetLanguages) router.GET(p+"/lang/:page", app.GetLanguages)
router.Use(static.Serve(p+"/", app.webFS)) router.Use(static.Serve(p+"/", app.webFS))
@ -140,6 +143,11 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
router.POST(p+"/invite/:invCode/matrix/user", app.MatrixSendPIN) router.POST(p+"/invite/:invCode/matrix/user", app.MatrixSendPIN)
router.POST(p+"/users/matrix", app.MatrixConnect) router.POST(p+"/users/matrix", app.MatrixConnect)
} }
if userPageEnabled {
router.GET(p+"/my/account", app.MyUserPage)
router.GET(p+"/my/token/login", app.getUserTokenLogin)
router.GET(p+"/my/token/refresh", app.getUserTokenRefresh)
}
} }
if *SWAGGER { if *SWAGGER {
app.info.Print(warning("\n\nWARNING: Swagger should not be used on a public instance.\n\n")) app.info.Print(warning("\n\nWARNING: Swagger should not be used on a public instance.\n\n"))
@ -147,7 +155,14 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
router.GET(p+"/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) router.GET(p+"/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
} }
} }
api := router.Group("/", app.webAuth()) api := router.Group("/", app.webAuth())
var user *gin.RouterGroup
if userPageEnabled {
user = router.Group("/my", app.userAuth())
}
for _, p := range routePrefixes { 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)
@ -210,6 +225,9 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
} }
api.POST(p+"/matrix/login", app.MatrixLogin) api.POST(p+"/matrix/login", app.MatrixLogin)
if userPageEnabled {
user.GET(p+"/hello", app.HelloWorld)
}
} }
} }

View File

@ -116,9 +116,9 @@ type Lang struct {
chosenAdminLang string chosenAdminLang string
Admin adminLangs Admin adminLangs
AdminJSON map[string]string AdminJSON map[string]string
FormPath string UserPath string
chosenFormLang string chosenUserLang string
Form formLangs User userLangs
PasswordResetPath string PasswordResetPath string
chosenPWRLang string chosenPWRLang string
PasswordReset pwrLangs PasswordReset pwrLangs
@ -144,7 +144,7 @@ func (st *Storage) loadLang(filesystems ...fs.FS) (err error) {
if err != nil { if err != nil {
return return
} }
err = st.loadLangForm(filesystems...) err = st.loadLangUser(filesystems...)
if err != nil { if err != nil {
return return
} }
@ -395,16 +395,16 @@ func (st *Storage) loadLangAdmin(filesystems ...fs.FS) error {
return nil return nil
} }
func (st *Storage) loadLangForm(filesystems ...fs.FS) error { func (st *Storage) loadLangUser(filesystems ...fs.FS) error {
st.lang.Form = map[string]formLang{} st.lang.User = map[string]userLang{}
var english formLang var english userLang
loadedLangs := make([]map[string]bool, len(filesystems)) loadedLangs := make([]map[string]bool, len(filesystems))
var load loadLangFunc var load loadLangFunc
load = func(fsIndex int, fname string) error { load = func(fsIndex int, fname string) error {
filesystem := filesystems[fsIndex] filesystem := filesystems[fsIndex]
index := strings.TrimSuffix(fname, filepath.Ext(fname)) index := strings.TrimSuffix(fname, filepath.Ext(fname))
lang := formLang{} lang := userLang{}
f, err := fs.ReadFile(filesystem, FSJoin(st.lang.FormPath, fname)) f, err := fs.ReadFile(filesystem, FSJoin(st.lang.UserPath, fname))
if err != nil { if err != nil {
return err return err
} }
@ -418,11 +418,11 @@ func (st *Storage) loadLangForm(filesystems ...fs.FS) error {
st.lang.Common.patchCommon(&lang.Strings, index) st.lang.Common.patchCommon(&lang.Strings, index)
if fname != "en-us.json" { if fname != "en-us.json" {
if lang.Meta.Fallback != "" { if lang.Meta.Fallback != "" {
fallback, ok := st.lang.Form[lang.Meta.Fallback] fallback, ok := st.lang.User[lang.Meta.Fallback]
err = nil err = nil
if !ok { if !ok {
err = load(fsIndex, lang.Meta.Fallback+".json") err = load(fsIndex, lang.Meta.Fallback+".json")
fallback = st.lang.Form[lang.Meta.Fallback] fallback = st.lang.User[lang.Meta.Fallback]
} }
if err == nil { if err == nil {
loadedLangs[fsIndex][lang.Meta.Fallback+".json"] = true loadedLangs[fsIndex][lang.Meta.Fallback+".json"] = true
@ -447,7 +447,7 @@ func (st *Storage) loadLangForm(filesystems ...fs.FS) error {
} }
lang.notificationsJSON = string(notifications) lang.notificationsJSON = string(notifications)
lang.validationStringsJSON = string(validationStrings) lang.validationStringsJSON = string(validationStrings)
st.lang.Form[index] = lang st.lang.User[index] = lang
return nil return nil
} }
engFound := false engFound := false
@ -463,10 +463,10 @@ func (st *Storage) loadLangForm(filesystems ...fs.FS) error {
if !engFound { if !engFound {
return err return err
} }
english = st.lang.Form["en-us"] english = st.lang.User["en-us"]
formLoaded := false userLoaded := false
for i := range filesystems { for i := range filesystems {
files, err := fs.ReadDir(filesystems[i], st.lang.FormPath) files, err := fs.ReadDir(filesystems[i], st.lang.UserPath)
if err != nil { if err != nil {
continue continue
} }
@ -474,13 +474,13 @@ func (st *Storage) loadLangForm(filesystems ...fs.FS) error {
if !loadedLangs[i][f.Name()] { if !loadedLangs[i][f.Name()] {
err = load(i, f.Name()) err = load(i, f.Name())
if err == nil { if err == nil {
formLoaded = true userLoaded = true
loadedLangs[i][f.Name()] = true loadedLangs[i][f.Name()] = true
} }
} }
} }
} }
if !formLoaded { if !userLoaded {
return err return err
} }
return nil return nil
@ -540,7 +540,7 @@ func (st *Storage) loadLangPWR(filesystems ...fs.FS) error {
return err return err
} }
english = st.lang.PasswordReset["en-us"] english = st.lang.PasswordReset["en-us"]
formLoaded := false userLoaded := false
for i := range filesystems { for i := range filesystems {
files, err := fs.ReadDir(filesystems[i], st.lang.PasswordResetPath) files, err := fs.ReadDir(filesystems[i], st.lang.PasswordResetPath)
if err != nil { if err != nil {
@ -550,13 +550,13 @@ func (st *Storage) loadLangPWR(filesystems ...fs.FS) error {
if !loadedLangs[i][f.Name()] { if !loadedLangs[i][f.Name()] {
err = load(i, f.Name()) err = load(i, f.Name())
if err == nil { if err == nil {
formLoaded = true userLoaded = true
loadedLangs[i][f.Name()] = true loadedLangs[i][f.Name()] = true
} }
} }
} }
} }
if !formLoaded { if !userLoaded {
return err return err
} }
return nil return nil

View File

@ -160,6 +160,7 @@ window.onpopstate = (event: PopStateEvent) => {
const login = new Login(window.modals.login as Modal, "/"); const login = new Login(window.modals.login as Modal, "/");
login.onLogin = () => { login.onLogin = () => {
console.log("Logged in.");
window.updater = new Updater(); window.updater = new Updater();
setInterval(() => { window.invites.reload(); accounts.reload(); }, 30*1000); setInterval(() => { window.invites.reload(); accounts.reload(); }, 30*1000);
const currentTab = window.tabs.current; const currentTab = window.tabs.current;

37
ts/user.ts Normal file
View File

@ -0,0 +1,37 @@
import { ThemeManager } from "./modules/theme.js";
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
import { Modal } from "./modules/modal.js";
import { _get, _post, notificationBox, whichAnimationEvent } from "./modules/common.js";
import { Login } from "./modules/login.js";
const theme = new ThemeManager(document.getElementById("button-theme"));
window.lang = new lang(window.langFile as LangFile);
loadLangSelector("user");
window.animationEvent = whichAnimationEvent();
window.token = "";
window.modals = {} as Modals;
(() => {
window.modals.login = new Modal(document.getElementById("modal-login"), true);
})();
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
const login = new Login(window.modals.login as Modal, "/my/");
login.onLogin = () => {
console.log("Logged in.");
document.getElementById("card-user").textContent = "Logged In!";
_get("/my/hello", null, (req: XMLHttpRequest) => {
if (req.readyState == 4) {
const card = document.getElementById("card-user");
card.textContent = card.textContent + " got response " + req.response["response"];
}
});
};
login.login("", "");

View File

@ -44,15 +44,23 @@ func gcHTML(gc *gin.Context, code int, file string, templ gin.H) {
gc.HTML(code, file, templ) gc.HTML(code, file, templ)
} }
func (app *appContext) pushResources(gc *gin.Context, admin bool) { func (app *appContext) pushResources(gc *gin.Context, page Page) {
var toPush []string
switch page {
case AdminPage:
toPush = []string{"/js/admin.js", "/js/theme.js", "/js/lang.js", "/js/modal.js", "/js/tabs.js", "/js/invites.js", "/js/accounts.js", "/js/settings.js", "/js/profiles.js", "/js/common.js"}
break
case UserPage:
toPush = []string{"/js/user.js", "/js/theme.js", "/js/lang.js", "/js/modal.js", "/js/common.js"}
break
default:
toPush = []string{}
}
if pusher := gc.Writer.Pusher(); pusher != nil { if pusher := gc.Writer.Pusher(); pusher != nil {
app.debug.Println("Using HTTP2 Server push") app.debug.Println("Using HTTP2 Server push")
if admin { for _, f := range toPush {
toPush := []string{"/js/admin.js", "/js/theme.js", "/js/lang.js", "/js/modal.js", "/js/tabs.js", "/js/invites.js", "/js/accounts.js", "/js/settings.js", "/js/profiles.js", "/js/common.js"} if err := pusher.Push(app.URLBase+f, nil); err != nil {
for _, f := range toPush { app.debug.Printf("Failed HTTP2 ServerPush of \"%s\": %+v", f, err)
if err := pusher.Push(app.URLBase+f, nil); err != nil {
app.debug.Printf("Failed HTTP2 ServerPush of \"%s\": %+v", f, err)
}
} }
} }
} }
@ -65,6 +73,8 @@ const (
AdminPage Page = iota + 1 AdminPage Page = iota + 1
FormPage FormPage
PWRPage PWRPage
UserPage
OtherPage
) )
func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string { func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string {
@ -77,8 +87,8 @@ func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string
gc.SetCookie("lang", lang, (365 * 3600), "/", gc.Request.URL.Hostname(), true, true) gc.SetCookie("lang", lang, (365 * 3600), "/", gc.Request.URL.Hostname(), true, true)
return lang return lang
} }
case FormPage: case FormPage, UserPage:
if _, ok := app.storage.lang.Form[lang]; ok { if _, ok := app.storage.lang.User[lang]; ok {
gc.SetCookie("lang", lang, (365 * 3600), "/", gc.Request.URL.Hostname(), true, true) gc.SetCookie("lang", lang, (365 * 3600), "/", gc.Request.URL.Hostname(), true, true)
return lang return lang
} }
@ -95,8 +105,8 @@ func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string
if _, ok := app.storage.lang.Admin[cookie]; ok { if _, ok := app.storage.lang.Admin[cookie]; ok {
return cookie return cookie
} }
case FormPage: case FormPage, UserPage:
if _, ok := app.storage.lang.Form[cookie]; ok { if _, ok := app.storage.lang.User[cookie]; ok {
return cookie return cookie
} }
case PWRPage: case PWRPage:
@ -109,7 +119,7 @@ func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string
} }
func (app *appContext) AdminPage(gc *gin.Context) { func (app *appContext) AdminPage(gc *gin.Context) {
app.pushResources(gc, true) app.pushResources(gc, AdminPage)
lang := app.getLang(gc, AdminPage, app.storage.lang.chosenAdminLang) lang := app.getLang(gc, AdminPage, app.storage.lang.chosenAdminLang)
emailEnabled, _ := app.config.Section("invite_emails").Key("enabled").Bool() emailEnabled, _ := app.config.Section("invite_emails").Key("enabled").Bool()
notificationsEnabled, _ := app.config.Section("notifications").Key("enabled").Bool() notificationsEnabled, _ := app.config.Section("notifications").Key("enabled").Bool()
@ -149,6 +159,32 @@ func (app *appContext) AdminPage(gc *gin.Context) {
}) })
} }
func (app *appContext) MyUserPage(gc *gin.Context) {
app.pushResources(gc, UserPage)
lang := app.getLang(gc, UserPage, app.storage.lang.chosenUserLang)
emailEnabled, _ := app.config.Section("invite_emails").Key("enabled").Bool()
notificationsEnabled, _ := app.config.Section("notifications").Key("enabled").Bool()
ombiEnabled := app.config.Section("ombi").Key("enabled").MustBool(false)
gcHTML(gc, http.StatusOK, "user.html", gin.H{
"urlBase": app.getURLBase(gc),
"cssClass": app.cssClass,
"cssVersion": cssVersion,
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
"emailEnabled": emailEnabled,
"telegramEnabled": telegramEnabled,
"discordEnabled": discordEnabled,
"matrixEnabled": matrixEnabled,
"ombiEnabled": ombiEnabled,
"linkResetEnabled": app.config.Section("password_resets").Key("link_reset").MustBool(false),
"notifications": notificationsEnabled,
"username": !app.config.Section("email").Key("no_username").MustBool(false),
"strings": app.storage.lang.Admin[lang].Strings,
"quantityStrings": app.storage.lang.Admin[lang].QuantityStrings,
"language": app.storage.lang.Admin[lang].JSON,
"langName": lang,
})
}
func (app *appContext) ResetPassword(gc *gin.Context) { func (app *appContext) ResetPassword(gc *gin.Context) {
isBot := strings.Contains(gc.Request.Header.Get("User-Agent"), "Bot") isBot := strings.Contains(gc.Request.Header.Get("User-Agent"), "Bot")
setPassword := app.config.Section("password_resets").Key("set_password").MustBool(false) setPassword := app.config.Section("password_resets").Key("set_password").MustBool(false)
@ -157,7 +193,7 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
app.NoRouteHandler(gc) app.NoRouteHandler(gc)
return return
} }
app.pushResources(gc, false) app.pushResources(gc, PWRPage)
lang := app.getLang(gc, PWRPage, app.storage.lang.chosenPWRLang) lang := app.getLang(gc, PWRPage, app.storage.lang.chosenPWRLang)
data := gin.H{ data := gin.H{
"urlBase": app.getURLBase(gc), "urlBase": app.getURLBase(gc),
@ -177,8 +213,8 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
data["validate"] = app.config.Section("password_validation").Key("enabled").MustBool(false) data["validate"] = app.config.Section("password_validation").Key("enabled").MustBool(false)
data["requirements"] = app.validator.getCriteria() data["requirements"] = app.validator.getCriteria()
data["strings"] = app.storage.lang.PasswordReset[lang].Strings data["strings"] = app.storage.lang.PasswordReset[lang].Strings
data["validationStrings"] = app.storage.lang.Form[lang].validationStringsJSON data["validationStrings"] = app.storage.lang.User[lang].validationStringsJSON
data["notifications"] = app.storage.lang.Form[lang].notificationsJSON data["notifications"] = app.storage.lang.User[lang].notificationsJSON
data["langName"] = lang data["langName"] = lang
data["passwordReset"] = true data["passwordReset"] = true
data["telegramEnabled"] = false data["telegramEnabled"] = false
@ -422,9 +458,9 @@ func (app *appContext) VerifyCaptcha(gc *gin.Context) {
} }
func (app *appContext) InviteProxy(gc *gin.Context) { func (app *appContext) InviteProxy(gc *gin.Context) {
app.pushResources(gc, false) app.pushResources(gc, FormPage)
code := gc.Param("invCode") code := gc.Param("invCode")
lang := app.getLang(gc, FormPage, app.storage.lang.chosenFormLang) lang := app.getLang(gc, FormPage, app.storage.lang.chosenUserLang)
/* Don't actually check if the invite is valid, just if it exists, just so the page loads quicker. Invite is actually checked on submit anyway. */ /* Don't actually check if the invite is valid, just if it exists, just so the page loads quicker. Invite is actually checked on submit anyway. */
// if app.checkInvite(code, false, "") { // if app.checkInvite(code, false, "") {
inv, ok := app.storage.invites[code] inv, ok := app.storage.invites[code]
@ -493,7 +529,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
} else { } else {
gcHTML(gc, http.StatusOK, "create-success.html", gin.H{ gcHTML(gc, http.StatusOK, "create-success.html", gin.H{
"cssClass": app.cssClass, "cssClass": app.cssClass,
"strings": app.storage.lang.Form[lang].Strings, "strings": app.storage.lang.User[lang].Strings,
"successMessage": app.config.Section("ui").Key("success_message").String(), "successMessage": app.config.Section("ui").Key("success_message").String(),
"contactMessage": app.config.Section("ui").Key("contact_message").String(), "contactMessage": app.config.Section("ui").Key("contact_message").String(),
"jfLink": jfLink, "jfLink": jfLink,
@ -528,9 +564,9 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
"requirements": app.validator.getCriteria(), "requirements": app.validator.getCriteria(),
"email": email, "email": email,
"username": !app.config.Section("email").Key("no_username").MustBool(false), "username": !app.config.Section("email").Key("no_username").MustBool(false),
"strings": app.storage.lang.Form[lang].Strings, "strings": app.storage.lang.User[lang].Strings,
"validationStrings": app.storage.lang.Form[lang].validationStringsJSON, "validationStrings": app.storage.lang.User[lang].validationStringsJSON,
"notifications": app.storage.lang.Form[lang].notificationsJSON, "notifications": app.storage.lang.User[lang].notificationsJSON,
"code": code, "code": code,
"confirmation": app.config.Section("email_confirmation").Key("enabled").MustBool(false), "confirmation": app.config.Section("email_confirmation").Key("enabled").MustBool(false),
"userExpiry": inv.UserExpiry, "userExpiry": inv.UserExpiry,
@ -538,7 +574,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
"userExpiryDays": inv.UserDays, "userExpiryDays": inv.UserDays,
"userExpiryHours": inv.UserHours, "userExpiryHours": inv.UserHours,
"userExpiryMinutes": inv.UserMinutes, "userExpiryMinutes": inv.UserMinutes,
"userExpiryMessage": app.storage.lang.Form[lang].Strings.get("yourAccountIsValidUntil"), "userExpiryMessage": app.storage.lang.User[lang].Strings.get("yourAccountIsValidUntil"),
"langName": lang, "langName": lang,
"passwordReset": false, "passwordReset": false,
"telegramEnabled": telegram, "telegramEnabled": telegram,
@ -563,7 +599,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
data["discordPIN"] = app.discord.NewAuthToken() data["discordPIN"] = app.discord.NewAuthToken()
data["discordUsername"] = app.discord.username data["discordUsername"] = app.discord.username
data["discordRequired"] = app.config.Section("discord").Key("required").MustBool(false) data["discordRequired"] = app.config.Section("discord").Key("required").MustBool(false)
data["discordSendPINMessage"] = template.HTML(app.storage.lang.Form[lang].Strings.template("sendPINDiscord", tmpl{ data["discordSendPINMessage"] = template.HTML(app.storage.lang.User[lang].Strings.template("sendPINDiscord", tmpl{
"command": `<span class="text-black dark:text-white font-mono">/` + app.config.Section("discord").Key("start_command").MustString("start") + `</span>`, "command": `<span class="text-black dark:text-white font-mono">/` + app.config.Section("discord").Key("start_command").MustString("start") + `</span>`,
"server_channel": app.discord.serverChannelName, "server_channel": app.discord.serverChannelName,
})) }))
@ -579,7 +615,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
} }
func (app *appContext) NoRouteHandler(gc *gin.Context) { func (app *appContext) NoRouteHandler(gc *gin.Context) {
app.pushResources(gc, false) app.pushResources(gc, OtherPage)
gcHTML(gc, 404, "404.html", gin.H{ gcHTML(gc, 404, "404.html", gin.H{
"cssClass": app.cssClass, "cssClass": app.cssClass,
"cssVersion": cssVersion, "cssVersion": cssVersion,