config: start adding path parameters
to change the urls of the admin page, the my account page and of invites. Seems to work, but need to check all the code over and test.
This commit is contained in:
+5
-5
@@ -414,7 +414,7 @@ func (app *appContext) TelegramVerified(gc *gin.Context) {
|
|||||||
respondBool(200, ok, gc)
|
respondBool(200, ok, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Returns true/false on whether or not a telegram PIN was verified. Requires invite code.
|
// @Summary Returns true/false on whether or not a telegram PIN was verified. Requires invite code. NOTE: "/invite" might have been changed in Settings > URL Paths.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
// @Success 401 {object} boolResponse
|
// @Success 401 {object} boolResponse
|
||||||
@@ -438,7 +438,7 @@ func (app *appContext) TelegramVerifiedInvite(gc *gin.Context) {
|
|||||||
respondBool(200, ok, gc)
|
respondBool(200, ok, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Returns true/false on whether or not a discord PIN was verified. Requires invite code.
|
// @Summary Returns true/false on whether or not a discord PIN was verified. Requires invite code. NOTE: "/invite" might have been changed in Settings > URL Paths.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
// @Failure 401 {object} boolResponse
|
// @Failure 401 {object} boolResponse
|
||||||
@@ -462,7 +462,7 @@ func (app *appContext) DiscordVerifiedInvite(gc *gin.Context) {
|
|||||||
respondBool(200, ok, gc)
|
respondBool(200, ok, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Returns a 10-minute, one-use Discord server invite
|
// @Summary Returns a 10-minute, one-use Discord server invite. NOTE: "/invite" might have been changed in Settings > URL Paths.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} DiscordInviteDTO
|
// @Success 200 {object} DiscordInviteDTO
|
||||||
// @Failure 400 {object} boolResponse
|
// @Failure 400 {object} boolResponse
|
||||||
@@ -489,7 +489,7 @@ func (app *appContext) DiscordServerInvite(gc *gin.Context) {
|
|||||||
gc.JSON(200, DiscordInviteDTO{invURL, iconURL})
|
gc.JSON(200, DiscordInviteDTO{invURL, iconURL})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Generate and send a new PIN to a specified Matrix user.
|
// @Summary Generate and send a new PIN to a specified Matrix user. NOTE: "/invite" might have been changed in Settings > URL Paths.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
// @Failure 400 {object} stringResponse
|
// @Failure 400 {object} stringResponse
|
||||||
@@ -528,7 +528,7 @@ func (app *appContext) MatrixSendPIN(gc *gin.Context) {
|
|||||||
respondBool(200, true, gc)
|
respondBool(200, true, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Check whether a matrix PIN is valid, and mark the token as verified if so. Requires invite code.
|
// @Summary Check whether a matrix PIN is valid, and mark the token as verified if so. Requires invite code. NOTE: "/invite" might have been changed in Settings > URL Paths.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
// @Failure 401 {object} boolResponse
|
// @Failure 401 {object} boolResponse
|
||||||
|
|||||||
+3
-5
@@ -164,9 +164,7 @@ func (app *appContext) confirmMyAction(gc *gin.Context, key string) {
|
|||||||
var target ConfirmationTarget
|
var target ConfirmationTarget
|
||||||
var id string
|
var id string
|
||||||
fail := func() {
|
fail := func() {
|
||||||
gcHTML(gc, 404, "404.html", gin.H{
|
app.gcHTML(gc, 404, "404.html", OtherPage, gin.H{
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -201,7 +199,7 @@ func (app *appContext) confirmMyAction(gc *gin.Context, key string) {
|
|||||||
|
|
||||||
// Perform an Action
|
// Perform an Action
|
||||||
if target == NoOp {
|
if target == NoOp {
|
||||||
gc.Redirect(http.StatusSeeOther, "/my/account")
|
gc.Redirect(http.StatusSeeOther, PAGES.MyAccount)
|
||||||
return
|
return
|
||||||
} else if target == UserEmailChange {
|
} else if target == UserEmailChange {
|
||||||
app.modifyEmail(id, claims["email"].(string))
|
app.modifyEmail(id, claims["email"].(string))
|
||||||
@@ -216,7 +214,7 @@ func (app *appContext) confirmMyAction(gc *gin.Context, key string) {
|
|||||||
}, gc, true)
|
}, gc, true)
|
||||||
|
|
||||||
app.info.Printf(lm.UserEmailAdjusted, gc.GetString("jfId"))
|
app.info.Printf(lm.UserEmailAdjusted, gc.GetString("jfId"))
|
||||||
gc.Redirect(http.StatusSeeOther, "/my/account")
|
gc.Redirect(http.StatusSeeOther, PAGES.MyAccount)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ var telegramEnabled = false
|
|||||||
var discordEnabled = false
|
var discordEnabled = false
|
||||||
var matrixEnabled = false
|
var matrixEnabled = false
|
||||||
|
|
||||||
|
// URL subpaths. Ignore the "Current" field.
|
||||||
|
var PAGES = PagePaths{}
|
||||||
|
|
||||||
func (app *appContext) GetPath(sect, key string) (fs.FS, string) {
|
func (app *appContext) GetPath(sect, key string) (fs.FS, string) {
|
||||||
val := app.config.Section(sect).Key(key).MustString("")
|
val := app.config.Section(sect).Key(key).MustString("")
|
||||||
if strings.HasPrefix(val, "jfa-go:") {
|
if strings.HasPrefix(val, "jfa-go:") {
|
||||||
@@ -35,6 +38,13 @@ func (app *appContext) MustSetValue(section, key, val string) {
|
|||||||
app.config.Section(section).Key(key).SetValue(app.config.Section(section).Key(key).MustString(val))
|
app.config.Section(section).Key(key).SetValue(app.config.Section(section).Key(key).MustString(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *appContext) MustSetURLPath(section, key, val string) {
|
||||||
|
if !strings.HasPrefix(val, "/") {
|
||||||
|
val = "/" + val
|
||||||
|
}
|
||||||
|
app.MustSetValue(section, key, val)
|
||||||
|
}
|
||||||
|
|
||||||
func (app *appContext) loadConfig() error {
|
func (app *appContext) loadConfig() error {
|
||||||
var err error
|
var err error
|
||||||
app.config, err = ini.ShadowLoad(app.configPath)
|
app.config, err = ini.ShadowLoad(app.configPath)
|
||||||
@@ -42,6 +52,13 @@ func (app *appContext) loadConfig() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.MustSetURLPath("url_paths", "admin", "/")
|
||||||
|
app.MustSetURLPath("url_paths", "user_page", "/my/account")
|
||||||
|
app.MustSetURLPath("url_paths", "form", "/invite")
|
||||||
|
PAGES.Admin = app.config.Section("url_paths").Key("admin").MustString("/")
|
||||||
|
PAGES.MyAccount = app.config.Section("url_paths").Key("user_page").MustString("/my/account")
|
||||||
|
PAGES.Form = app.config.Section("url_paths").Key("form").MustString("/invite")
|
||||||
|
|
||||||
app.MustSetValue("jellyfin", "public_server", app.config.Section("jellyfin").Key("server").String())
|
app.MustSetValue("jellyfin", "public_server", app.config.Section("jellyfin").Key("server").String())
|
||||||
|
|
||||||
app.MustSetValue("ui", "redirect_url", app.config.Section("jellyfin").Key("public_server").String())
|
app.MustSetValue("ui", "redirect_url", app.config.Section("jellyfin").Key("public_server").String())
|
||||||
@@ -58,12 +75,12 @@ func (app *appContext) loadConfig() error {
|
|||||||
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".db"))))
|
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".db"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
app.URLBase = strings.TrimSuffix(app.config.Section("ui").Key("url_base").MustString(""), "/")
|
PAGES.Base = strings.TrimSuffix(app.config.Section("ui").Key("url_base").MustString(""), "/")
|
||||||
if app.URLBase == "/invite" || app.URLBase == "/accounts" || app.URLBase == "/settings" || app.URLBase == "/activity" {
|
if PAGES.Base == "/invite" || PAGES.Base == "/accounts" || PAGES.Base == "/settings" || PAGES.Base == "/activity" {
|
||||||
app.err.Printf(lm.BadURLBase, app.URLBase)
|
app.err.Printf(lm.BadURLBase, PAGES.Base)
|
||||||
}
|
}
|
||||||
app.ExternalURI = strings.TrimSuffix(strings.TrimSuffix(app.config.Section("ui").Key("jfa_url").MustString(""), "/invite"), "/")
|
app.ExternalURI = strings.TrimSuffix(strings.TrimSuffix(app.config.Section("ui").Key("jfa_url").MustString(""), "/invite"), "/")
|
||||||
if !strings.HasSuffix(app.ExternalURI, app.URLBase) {
|
if !strings.HasSuffix(app.ExternalURI, PAGES.Base) {
|
||||||
app.err.Println(lm.NoURLSuffix)
|
app.err.Println(lm.NoURLSuffix)
|
||||||
}
|
}
|
||||||
if app.ExternalURI == "" {
|
if app.ExternalURI == "" {
|
||||||
|
|||||||
@@ -232,6 +232,33 @@ sections:
|
|||||||
- ["opaque", "Opaque"]
|
- ["opaque", "Opaque"]
|
||||||
value: clear
|
value: clear
|
||||||
description: Appearance of the Admin login screen.
|
description: Appearance of the Admin login screen.
|
||||||
|
- section: url_paths
|
||||||
|
meta:
|
||||||
|
name: URL Paths
|
||||||
|
description: Settings for changing where different pages are accessed.
|
||||||
|
advanced: true
|
||||||
|
settings:
|
||||||
|
- setting: admin
|
||||||
|
name: Admin page subpath
|
||||||
|
type: text
|
||||||
|
required: true
|
||||||
|
requires_restart: true
|
||||||
|
value: "/"
|
||||||
|
description: URL subpath the admin page should be at.
|
||||||
|
- setting: user_page
|
||||||
|
name: "\"My Account\" subpath"
|
||||||
|
type: text
|
||||||
|
required: true
|
||||||
|
requires_restart: true
|
||||||
|
value: "/my/account"
|
||||||
|
description: URL subpath the "My Account" page should be at.
|
||||||
|
- setting: form
|
||||||
|
name: Invite subpath
|
||||||
|
type: text
|
||||||
|
required: true
|
||||||
|
requires_restart: true
|
||||||
|
value: "/invite"
|
||||||
|
description: URL subpath invites should be on.
|
||||||
- section: advanced
|
- section: advanced
|
||||||
meta:
|
meta:
|
||||||
name: Advanced
|
name: Advanced
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ func (emailer *Emailer) confirmationValues(code, username, key string, app *appC
|
|||||||
if code == "" { // Personal email change
|
if code == "" { // Personal email change
|
||||||
inviteLink = fmt.Sprintf("%s/my/confirm/%s", inviteLink, url.PathEscape(key))
|
inviteLink = fmt.Sprintf("%s/my/confirm/%s", inviteLink, url.PathEscape(key))
|
||||||
} else { // Invite email confirmation
|
} else { // Invite email confirmation
|
||||||
inviteLink = fmt.Sprintf("%s/invite/%s?key=%s", inviteLink, code, url.PathEscape(key))
|
inviteLink = fmt.Sprintf("%s%s/%s?key=%s", inviteLink, PAGES.Form, code, url.PathEscape(key))
|
||||||
}
|
}
|
||||||
template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": username})
|
template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": username})
|
||||||
template["confirmationURL"] = inviteLink
|
template["confirmationURL"] = inviteLink
|
||||||
@@ -393,7 +393,7 @@ func (emailer *Emailer) inviteValues(code string, invite Invite, app *appContext
|
|||||||
expiry := invite.ValidTill
|
expiry := invite.ValidTill
|
||||||
d, t, expiresIn := emailer.formatExpiry(expiry, false, app.datePattern, app.timePattern)
|
d, t, expiresIn := emailer.formatExpiry(expiry, false, app.datePattern, app.timePattern)
|
||||||
message := app.config.Section("messages").Key("message").String()
|
message := app.config.Section("messages").Key("message").String()
|
||||||
inviteLink := fmt.Sprintf("%s/invite/%s", app.ExternalURI, code)
|
inviteLink := fmt.Sprintf("%s%s/%s", app.ExternalURI, PAGES.Form, code)
|
||||||
template := map[string]interface{}{
|
template := map[string]interface{}{
|
||||||
"hello": emailer.lang.InviteEmail.get("hello"),
|
"hello": emailer.lang.InviteEmail.get("hello"),
|
||||||
"youHaveBeenInvited": emailer.lang.InviteEmail.get("youHaveBeenInvited"),
|
"youHaveBeenInvited": emailer.lang.InviteEmail.get("youHaveBeenInvited"),
|
||||||
|
|||||||
+1
-2
@@ -1,9 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="css/{{ .cssVersion }}bundle.css">
|
|
||||||
{{ template "header.html" . }}
|
|
||||||
<title>404 - jfa-go</title>
|
<title>404 - jfa-go</title>
|
||||||
|
{{ template "header.html" . }}
|
||||||
</head>
|
</head>
|
||||||
<body class="section">
|
<body class="section">
|
||||||
<div class="page-container m-2 lg:my-20 lg:mx-64">
|
<div class="page-container m-2 lg:my-20 lg:mx-64">
|
||||||
|
|||||||
+3
-13
@@ -1,16 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ .urlBase }}/css/{{ .cssVersion }}bundle.css">
|
|
||||||
<script>
|
<script>
|
||||||
window.URLBase = "{{ .urlBase }}";
|
|
||||||
window.notificationsEnabled = {{ .notifications }};
|
|
||||||
window.emailEnabled = {{ .emailEnabled }};
|
|
||||||
window.telegramEnabled = {{ .telegramEnabled }};
|
|
||||||
window.discordEnabled = {{ .discordEnabled }};
|
|
||||||
window.matrixEnabled = {{ .matrixEnabled }};
|
|
||||||
window.ombiEnabled = {{ .ombiEnabled }};
|
|
||||||
window.jellyseerrEnabled = {{ .jellyseerrEnabled }};
|
|
||||||
window.usernameEnabled = {{ .username }};
|
window.usernameEnabled = {{ .username }};
|
||||||
window.langFile = JSON.parse({{ .language }});
|
window.langFile = JSON.parse({{ .language }});
|
||||||
window.linkResetEnabled = {{ .linkResetEnabled }};
|
window.linkResetEnabled = {{ .linkResetEnabled }};
|
||||||
@@ -18,7 +9,6 @@
|
|||||||
window.jellyfinLogin = {{ .jellyfinLogin }};
|
window.jellyfinLogin = {{ .jellyfinLogin }};
|
||||||
window.jfAdminOnly = {{ .jfAdminOnly }};
|
window.jfAdminOnly = {{ .jfAdminOnly }};
|
||||||
window.jfAllowAll = {{ .jfAllowAll }};
|
window.jfAllowAll = {{ .jfAllowAll }};
|
||||||
window.referralsEnabled = {{ .referralsEnabled }};
|
|
||||||
window.loginAppearance = "{{ .loginAppearance }}";
|
window.loginAppearance = "{{ .loginAppearance }}";
|
||||||
</script>
|
</script>
|
||||||
<title>Admin - jfa-go</title>
|
<title>Admin - jfa-go</title>
|
||||||
@@ -47,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="modal-about" class="modal">
|
<div id="modal-about" class="modal">
|
||||||
<div class="relative mx-auto my-[10%] w-11/12 sm:w-4/5 lg:w-1/2 content card">
|
<div class="relative mx-auto my-[10%] w-11/12 sm:w-4/5 lg:w-1/2 content card">
|
||||||
<img src="{{ .urlBase }}/banner.svg" class="banner header" alt="jfa-go banner">
|
<img src="{{ .pages.Base }}/banner.svg" class="banner header" alt="jfa-go banner">
|
||||||
<span class="heading"><span class="modal-close">×</span></span>
|
<span class="heading"><span class="modal-close">×</span></span>
|
||||||
<p>{{ .strings.version }} <span class="text-black dark:text-white font-mono bg-inherit">{{ .version }}</span></p>
|
<p>{{ .strings.version }} <span class="text-black dark:text-white font-mono bg-inherit">{{ .version }}</span></p>
|
||||||
<p>{{ .strings.commitNoun }} <span class="text-black dark:text-white font-mono bg-inherit">{{ .commit }}</span></p>
|
<p>{{ .strings.commitNoun }} <span class="text-black dark:text-white font-mono bg-inherit">{{ .commit }}</span></p>
|
||||||
@@ -551,7 +541,7 @@
|
|||||||
<span class="button ~critical @low unfocused" id="logout-button">{{ .strings.logout }}</span>
|
<span class="button ~critical @low unfocused" id="logout-button">{{ .strings.logout }}</span>
|
||||||
{{ if .userPageEnabled }}
|
{{ if .userPageEnabled }}
|
||||||
<div class="">
|
<div class="">
|
||||||
<a class="button ~info" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
<a class="button ~info" href="{{ .pages.Base }}{{ .pages.MyAccount }}"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
@@ -925,6 +915,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ .urlBase }}/js/admin.js" type="module"></script>
|
<script src="{{ .pages.Base }}/js/admin.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<!--- This CSS is inlined so we should keep this here! -->
|
||||||
<link inline rel="stylesheet" type="text/css" href="web/css/v3bundle.css">
|
<link inline rel="stylesheet" type="text/css" href="web/css/v3bundle.css">
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>Crash report</title>
|
<title>Crash report</title>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ .urlBase }}/css/{{ .cssVersion }}bundle.css">
|
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>{{ .strings.successHeader }} - jfa-go</title>
|
<title>{{ .strings.successHeader }} - jfa-go</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
window.usernameEnabled = {{ .username }};
|
window.usernameEnabled = {{ .username }};
|
||||||
window.validationStrings = JSON.parse({{ .validationStrings }});
|
window.validationStrings = JSON.parse({{ .validationStrings }});
|
||||||
window.invalidPassword = "{{ .strings.reEnterPasswordInvalid }}";
|
window.invalidPassword = "{{ .strings.reEnterPasswordInvalid }}";
|
||||||
window.URLBase = "{{ .urlBase }}";
|
|
||||||
window.code = "{{ .code }}";
|
window.code = "{{ .code }}";
|
||||||
window.language = "{{ .langName }}";
|
window.language = "{{ .langName }}";
|
||||||
window.messages = JSON.parse({{ .notifications }});
|
window.messages = JSON.parse({{ .notifications }});
|
||||||
@@ -14,16 +13,13 @@
|
|||||||
window.userExpiryHours = {{ .userExpiryHours }};
|
window.userExpiryHours = {{ .userExpiryHours }};
|
||||||
window.userExpiryMinutes = {{ .userExpiryMinutes }};
|
window.userExpiryMinutes = {{ .userExpiryMinutes }};
|
||||||
window.userExpiryMessage = {{ .userExpiryMessage }};
|
window.userExpiryMessage = {{ .userExpiryMessage }};
|
||||||
window.telegramEnabled = {{ .telegramEnabled }};
|
|
||||||
window.telegramRequired = {{ .telegramRequired }};
|
window.telegramRequired = {{ .telegramRequired }};
|
||||||
window.telegramPIN = "{{ .telegramPIN }}";
|
window.telegramPIN = "{{ .telegramPIN }}";
|
||||||
window.emailRequired = {{ .emailRequired }};
|
window.emailRequired = {{ .emailRequired }};
|
||||||
window.discordEnabled = {{ .discordEnabled }};
|
|
||||||
window.discordRequired = {{ .discordRequired }};
|
window.discordRequired = {{ .discordRequired }};
|
||||||
window.discordPIN = "{{ .discordPIN }}";
|
window.discordPIN = "{{ .discordPIN }}";
|
||||||
window.discordInviteLink = {{ .discordInviteLink }};
|
window.discordInviteLink = {{ .discordInviteLink }};
|
||||||
window.discordServerName = "{{ .discordServerName }}";
|
window.discordServerName = "{{ .discordServerName }}";
|
||||||
window.matrixEnabled = {{ .matrixEnabled }};
|
|
||||||
window.matrixRequired = {{ .matrixRequired }};
|
window.matrixRequired = {{ .matrixRequired }};
|
||||||
window.matrixUserID = "{{ .matrixUser }}";
|
window.matrixUserID = "{{ .matrixUser }}";
|
||||||
window.captcha = {{ .captcha }};
|
window.captcha = {{ .captcha }};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="css/{{ .cssVersion }}bundle.css">
|
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
{{ if .passwordReset }}
|
{{ if .passwordReset }}
|
||||||
<title>{{ .strings.passwordReset }}</title>
|
<title>{{ .strings.passwordReset }}</title>
|
||||||
|
|||||||
+24
-5
@@ -1,13 +1,32 @@
|
|||||||
|
<link rel="stylesheet" type="text/css" href="{{ .pages.Base }}/css/{{ .cssVersion }}bundle.css">
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="Description" content="jfa-go, a better way to manage Jellyfin users.">
|
<meta name="Description" content="jfa-go, a better way to manage Jellyfin users.">
|
||||||
<meta name="color-scheme" content="dark light">
|
<meta name="color-scheme" content="dark light">
|
||||||
<meta name="robots" content="noindex">
|
<meta name="robots" content="noindex">
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ .urlBase }}/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ .pages.Base }}/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ .urlBase }}/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ .pages.Base }}/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ .urlBase }}/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ .pages.Base }}/favicon-16x16.png">
|
||||||
<link rel="manifest" href="{{ .urlBase }}/site.webmanifest">
|
<link rel="manifest" href="{{ .pages.Base }}/site.webmanifest">
|
||||||
<link rel="mask-icon" href="{{ .urlBase }}/safari-pinned-tab.svg" color="#5bbad5">
|
<link rel="mask-icon" href="{{ .pages.Base }}/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
<meta name="msapplication-TileColor" content="#603cba">
|
<meta name="msapplication-TileColor" content="#603cba">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
<script>
|
||||||
|
window.pages = {
|
||||||
|
"Base": "{{ .pages.Base }}",
|
||||||
|
"Current": "{{ .pages.Current }}",
|
||||||
|
"Admin": "{{ .pages.Admin }}",
|
||||||
|
"MyAccount": "{{ .pages.MyAccount }}",
|
||||||
|
"Form": "{{ .pages.Form }}"
|
||||||
|
};
|
||||||
|
window.emailEnabled = {{ .emailEnabled }};
|
||||||
|
window.discordEnabled = {{ .discordEnabled }};
|
||||||
|
window.telegramEnabled = {{ .telegramEnabled }};
|
||||||
|
window.matrixEnabled = {{ .matrixEnabled }};
|
||||||
|
window.notificationsEnabled = {{ .notifications }};
|
||||||
|
window.ombiEnabled = {{ .ombiEnabled }};
|
||||||
|
window.jellyseerrEnabled = {{ .jellyseerrEnabled }};
|
||||||
|
window.referralsEnabled = {{ .referralsEnabled }};
|
||||||
|
window.pwrEnabled = {{ .pwrEnabled }};
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ .urlBase }}/css/{{ .cssVersion }}bundle.css">
|
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>Invalid Code - jfa-go</title>
|
<title>Invalid Code - jfa-go</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
{{ $hasTwoCards = 1 }}
|
{{ $hasTwoCards = 1 }}
|
||||||
<div class="card mx-2 flex-initial w-full lg:w-[35%] mb-4 lg:mb-0 dark:~d_neutral @low content">
|
<div class="card mx-2 flex-initial w-full lg:w-[35%] mb-4 lg:mb-0 dark:~d_neutral @low content">
|
||||||
<span class="heading row">{{ .strings.loginNotAdmin }}</span>
|
<span class="heading row">{{ .strings.loginNotAdmin }}</span>
|
||||||
<a class="button ~info h-12 w-full" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
<a class="button ~info h-12 w-full" href="{{ .pages.Base }}{{ .pages.MyAccount }}"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="css/{{ .cssVersion }}bundle.css">
|
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>{{ .strings.passwordReset }} - jfa-go</title>
|
<title>{{ .strings.passwordReset }} - jfa-go</title>
|
||||||
</head>
|
</head>
|
||||||
@@ -40,6 +39,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<i class="content">{{ .contactMessage }}</i>
|
<i class="content">{{ .contactMessage }}</i>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ .urlBase }}/js/pwr-pin.js" type="module"></script>
|
<script src="{{ .pages.Base }}/js/pwr-pin.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="light">
|
<html lang="en" class="light">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="css/{{ .cssVersion }}bundle.css">
|
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>{{ .lang.Strings.pageTitle }}</title>
|
<title>{{ .lang.Strings.pageTitle }}</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
+1
-11
@@ -1,31 +1,21 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="light">
|
<html lang="en" class="light">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ .urlBase }}/css/{{ .cssVersion }}bundle.css">
|
|
||||||
<script>
|
<script>
|
||||||
window.URLBase = "{{ .urlBase }}";
|
|
||||||
window.notificationsEnabled = {{ .notifications }};
|
|
||||||
window.ombiEnabled = {{ .ombiEnabled }};
|
|
||||||
window.langFile = JSON.parse({{ .language }});
|
window.langFile = JSON.parse({{ .language }});
|
||||||
window.pwrEnabled = {{ .pwrEnabled }};
|
|
||||||
window.linkResetEnabled = {{ .linkResetEnabled }};
|
window.linkResetEnabled = {{ .linkResetEnabled }};
|
||||||
window.language = "{{ .langName }}";
|
window.language = "{{ .langName }}";
|
||||||
window.telegramEnabled = {{ .telegramEnabled }};
|
|
||||||
window.telegramRequired = {{ .telegramRequired }};
|
window.telegramRequired = {{ .telegramRequired }};
|
||||||
window.telegramUsername = {{ .telegramUsername }};
|
window.telegramUsername = {{ .telegramUsername }};
|
||||||
window.telegramURL = {{ .telegramURL }};
|
window.telegramURL = {{ .telegramURL }};
|
||||||
window.emailEnabled = {{ .emailEnabled }};
|
|
||||||
window.emailRequired = {{ .emailRequired }};
|
window.emailRequired = {{ .emailRequired }};
|
||||||
window.discordEnabled = {{ .discordEnabled }};
|
|
||||||
window.discordRequired = {{ .discordRequired }};
|
window.discordRequired = {{ .discordRequired }};
|
||||||
window.discordServerName = "{{ .discordServerName }}";
|
window.discordServerName = "{{ .discordServerName }}";
|
||||||
window.discordInviteLink = {{ .discordInviteLink }};
|
window.discordInviteLink = {{ .discordInviteLink }};
|
||||||
window.discordSendPINMessage = "{{ .discordSendPINMessage }}";
|
window.discordSendPINMessage = "{{ .discordSendPINMessage }}";
|
||||||
window.matrixEnabled = {{ .matrixEnabled }};
|
|
||||||
window.matrixRequired = {{ .matrixRequired }};
|
window.matrixRequired = {{ .matrixRequired }};
|
||||||
window.matrixUserID = "{{ .matrixUser }}";
|
window.matrixUserID = "{{ .matrixUser }}";
|
||||||
window.validationStrings = JSON.parse({{ .validationStrings }});
|
window.validationStrings = JSON.parse({{ .validationStrings }});
|
||||||
window.referralsEnabled = {{ .referralsEnabled }};
|
|
||||||
</script>
|
</script>
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>{{ .strings.myAccount }}</title>
|
<title>{{ .strings.myAccount }}</title>
|
||||||
@@ -156,7 +146,7 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ .urlBase }}/js/user.js" type="module"></script>
|
<script src="{{ .pages.Base }}/js/user.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ type appContext struct {
|
|||||||
host string
|
host string
|
||||||
port int
|
port int
|
||||||
version string
|
version string
|
||||||
URLBase, ExternalURI, ExternalDomain string
|
ExternalURI, ExternalDomain string
|
||||||
updater *Updater
|
updater *Updater
|
||||||
webhooks *WebhookSender
|
webhooks *WebhookSender
|
||||||
newUpdate bool // Whether whatever's in update is new.
|
newUpdate bool // Whether whatever's in update is new.
|
||||||
@@ -147,7 +147,7 @@ func generateSecret(length int) (string, error) {
|
|||||||
|
|
||||||
func test(app *appContext) {
|
func test(app *appContext) {
|
||||||
fmt.Printf("\n\n----\n\n")
|
fmt.Printf("\n\n----\n\n")
|
||||||
settings := map[string]interface{}{
|
settings := map[string]any{
|
||||||
"server": app.jf.Server,
|
"server": app.jf.Server,
|
||||||
"server version": app.jf.ServerInfo.Version,
|
"server version": app.jf.ServerInfo.Version,
|
||||||
"server name": app.jf.ServerInfo.Name,
|
"server name": app.jf.ServerInfo.Name,
|
||||||
|
|||||||
@@ -467,3 +467,18 @@ type ContactMethodKey struct {
|
|||||||
PIN string
|
PIN string
|
||||||
User ContactMethodUser
|
User ContactMethodUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PagePaths struct {
|
||||||
|
// The base subfolder the app is hosted on.
|
||||||
|
Base string `json:"Base"`
|
||||||
|
// Those for other pages
|
||||||
|
Admin string `json:"Admin"`
|
||||||
|
MyAccount string `json:"MyAccount"`
|
||||||
|
Form string `json:"Form"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PagePathsDTO struct {
|
||||||
|
PagePaths
|
||||||
|
// The subdirectory this bit of the app is hosted on (e.g. admin is usually on "/", myacc is usually on "/my/account")
|
||||||
|
Current string `json:"Current"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,8 +108,8 @@ func (app *appContext) loadRouter(address string, debug bool) *gin.Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) loadRoutes(router *gin.Engine) {
|
func (app *appContext) loadRoutes(router *gin.Engine) {
|
||||||
routePrefixes := []string{app.URLBase}
|
routePrefixes := []string{PAGES.Base}
|
||||||
if app.URLBase != "" {
|
if PAGES.Base != "" {
|
||||||
routePrefixes = append(routePrefixes, "")
|
routePrefixes = append(routePrefixes, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
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))
|
||||||
router.GET(p+"/", app.AdminPage)
|
router.GET(p+PAGES.Admin, app.AdminPage)
|
||||||
|
|
||||||
if app.config.Section("password_resets").Key("link_reset").MustBool(false) {
|
if app.config.Section("password_resets").Key("link_reset").MustBool(false) {
|
||||||
router.GET(p+"/reset", app.ResetPassword)
|
router.GET(p+"/reset", app.ResetPassword)
|
||||||
@@ -127,39 +127,39 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.GET(p+"/accounts", app.AdminPage)
|
router.GET(p+PAGES.Admin+"/accounts", app.AdminPage)
|
||||||
router.GET(p+"/settings", app.AdminPage)
|
router.GET(p+PAGES.Admin+"/settings", app.AdminPage)
|
||||||
router.GET(p+"/activity", app.AdminPage)
|
router.GET(p+PAGES.Admin+"/activity", app.AdminPage)
|
||||||
router.GET(p+"/accounts/user/:userID", app.AdminPage)
|
router.GET(p+PAGES.Admin+"/accounts/user/:userID", app.AdminPage)
|
||||||
router.GET(p+"/invites/:code", app.AdminPage)
|
router.GET(p+PAGES.Admin+"/invites/:code", app.AdminPage)
|
||||||
router.GET(p+"/lang/:page/:file", app.ServeLang)
|
router.GET(p+"/lang/:page/:file", app.ServeLang)
|
||||||
router.GET(p+"/token/login", app.getTokenLogin)
|
router.GET(p+"/token/login", app.getTokenLogin)
|
||||||
router.GET(p+"/token/refresh", app.getTokenRefresh)
|
router.GET(p+"/token/refresh", app.getTokenRefresh)
|
||||||
router.POST(p+"/user/invite", app.NewUserFromInvite)
|
router.POST(p+"/user/invite", app.NewUserFromInvite)
|
||||||
router.Use(static.Serve(p+"/invite/", app.webFS))
|
router.Use(static.Serve(p+PAGES.Form, app.webFS))
|
||||||
router.GET(p+"/invite/:invCode", app.InviteProxy)
|
router.GET(p+PAGES.Form+"/:invCode", app.InviteProxy)
|
||||||
if app.config.Section("captcha").Key("enabled").MustBool(false) {
|
if app.config.Section("captcha").Key("enabled").MustBool(false) {
|
||||||
router.GET(p+"/captcha/gen/:invCode", app.GenCaptcha)
|
router.GET(p+"/captcha/gen/:invCode", app.GenCaptcha)
|
||||||
router.GET(p+"/captcha/img/:invCode/:captchaID", app.GetCaptcha)
|
router.GET(p+"/captcha/img/:invCode/:captchaID", app.GetCaptcha)
|
||||||
router.POST(p+"/captcha/verify/:invCode/:captchaID/:text", app.VerifyCaptcha)
|
router.POST(p+"/captcha/verify/:invCode/:captchaID/:text", app.VerifyCaptcha)
|
||||||
}
|
}
|
||||||
if telegramEnabled {
|
if telegramEnabled {
|
||||||
router.GET(p+"/invite/:invCode/telegram/verified/:pin", app.TelegramVerifiedInvite)
|
router.GET(p+PAGES.Form+"/:invCode/telegram/verified/:pin", app.TelegramVerifiedInvite)
|
||||||
}
|
}
|
||||||
if discordEnabled {
|
if discordEnabled {
|
||||||
router.GET(p+"/invite/:invCode/discord/verified/:pin", app.DiscordVerifiedInvite)
|
router.GET(p+PAGES.Form+"/:invCode/discord/verified/:pin", app.DiscordVerifiedInvite)
|
||||||
if app.config.Section("discord").Key("provide_invite").MustBool(false) {
|
if app.config.Section("discord").Key("provide_invite").MustBool(false) {
|
||||||
router.GET(p+"/invite/:invCode/discord/invite", app.DiscordServerInvite)
|
router.GET(p+PAGES.Form+"/:invCode/discord/invite", app.DiscordServerInvite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matrixEnabled {
|
if matrixEnabled {
|
||||||
router.GET(p+"/invite/:invCode/matrix/verified/:userID/:pin", app.MatrixCheckPIN)
|
router.GET(p+PAGES.Form+"/:invCode/matrix/verified/:userID/:pin", app.MatrixCheckPIN)
|
||||||
router.POST(p+"/invite/:invCode/matrix/user", app.MatrixSendPIN)
|
router.POST(p+PAGES.Form+"/:invCode/matrix/user", app.MatrixSendPIN)
|
||||||
router.POST(p+"/users/matrix", app.MatrixConnect)
|
router.POST(p+"/users/matrix", app.MatrixConnect)
|
||||||
}
|
}
|
||||||
if userPageEnabled {
|
if userPageEnabled {
|
||||||
router.GET(p+"/my/account", app.MyUserPage)
|
router.GET(p+PAGES.MyAccount, app.MyUserPage)
|
||||||
router.GET(p+"/my/account/password/reset", app.MyUserPage)
|
router.GET(p+PAGES.MyAccount+"/password/reset", app.MyUserPage)
|
||||||
router.GET(p+"/my/token/login", app.getUserTokenLogin)
|
router.GET(p+"/my/token/login", app.getUserTokenLogin)
|
||||||
router.GET(p+"/my/token/refresh", app.getUserTokenRefresh)
|
router.GET(p+"/my/token/refresh", app.getUserTokenRefresh)
|
||||||
router.GET(p+"/my/confirm/:jwt", app.ConfirmMyAction)
|
router.GET(p+"/my/confirm/:jwt", app.ConfirmMyAction)
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ func (app *appContext) ServeSetup(gc *gin.Context) {
|
|||||||
respond(500, "Failed to fetch default values", gc)
|
respond(500, "Failed to fetch default values", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
pages := PagePathsDTO{PagePaths: PAGES}
|
||||||
gc.HTML(200, "setup.html", gin.H{
|
gc.HTML(200, "setup.html", gin.H{
|
||||||
"cssVersion": cssVersion,
|
"cssVersion": cssVersion,
|
||||||
|
"pages": pages,
|
||||||
"lang": app.storage.lang.Setup[lang],
|
"lang": app.storage.lang.Setup[lang],
|
||||||
"strings": app.storage.lang.Setup[lang].Strings,
|
"strings": app.storage.lang.Setup[lang].Strings,
|
||||||
"emailLang": app.storage.lang.Email[emailLang],
|
"emailLang": app.storage.lang.Email[emailLang],
|
||||||
|
|||||||
+5
-3
@@ -11,6 +11,8 @@ import { _get, _post, notificationBox, whichAnimationEvent, bindManualDropdowns
|
|||||||
import { Updater } from "./modules/update.js";
|
import { Updater } from "./modules/update.js";
|
||||||
import { Login } from "./modules/login.js";
|
import { Login } from "./modules/login.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
const theme = new ThemeManager(document.getElementById("button-theme"));
|
const theme = new ThemeManager(document.getElementById("button-theme"));
|
||||||
|
|
||||||
window.lang = new lang(window.langFile as LangFile);
|
window.lang = new lang(window.langFile as LangFile);
|
||||||
@@ -165,12 +167,12 @@ const defaultTab = tabs[0];
|
|||||||
window.tabs = new Tabs();
|
window.tabs = new Tabs();
|
||||||
|
|
||||||
for (let tab of tabs) {
|
for (let tab of tabs) {
|
||||||
window.tabs.addTab(tab.id, tab.url, null, tab.reloader);
|
window.tabs.addTab(tab.id, window.pages.Admin + "/" + tab.url, null, tab.reloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
let matchedTab = false
|
let matchedTab = false
|
||||||
for (let tab of tabs) {
|
for (const tab of tabs) {
|
||||||
if (window.location.pathname.startsWith(window.URLBase + "/" + tab.url)) {
|
if (window.location.pathname.startsWith(window.pages.Base + window.pages.Current + "/" + tab.url)) {
|
||||||
window.tabs.switch(tab.url, true);
|
window.tabs.switch(tab.url, true);
|
||||||
matchedTab = true;
|
matchedTab = true;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -6,7 +6,7 @@ import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.
|
|||||||
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
|
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
|
||||||
import { Captcha, GreCAPTCHA } from "./modules/captcha.js";
|
import { Captcha, GreCAPTCHA } from "./modules/captcha.js";
|
||||||
|
|
||||||
interface formWindow extends Window {
|
interface formWindow extends GlobalWindow {
|
||||||
invalidPassword: string;
|
invalidPassword: string;
|
||||||
successModal: Modal;
|
successModal: Modal;
|
||||||
telegramModal: Modal;
|
telegramModal: Modal;
|
||||||
@@ -59,7 +59,7 @@ if (window.telegramEnabled) {
|
|||||||
modal: window.telegramModal as Modal,
|
modal: window.telegramModal as Modal,
|
||||||
pin: window.telegramPIN,
|
pin: window.telegramPIN,
|
||||||
pinURL: "",
|
pinURL: "",
|
||||||
verifiedURL: "/invite/" + window.code + "/telegram/verified/",
|
verifiedURL: window.pages.Form + "/" + window.code + "/telegram/verified/",
|
||||||
invalidCodeError: window.messages["errorInvalidPIN"],
|
invalidCodeError: window.messages["errorInvalidPIN"],
|
||||||
accountLinkedError: window.messages["errorAccountLinked"],
|
accountLinkedError: window.messages["errorAccountLinked"],
|
||||||
successError: window.messages["verified"],
|
successError: window.messages["verified"],
|
||||||
@@ -89,9 +89,9 @@ if (window.discordEnabled) {
|
|||||||
const discordConf: ServiceConfiguration = {
|
const discordConf: ServiceConfiguration = {
|
||||||
modal: window.discordModal as Modal,
|
modal: window.discordModal as Modal,
|
||||||
pin: window.discordPIN,
|
pin: window.discordPIN,
|
||||||
inviteURL: window.discordInviteLink ? ("/invite/" + window.code + "/discord/invite") : "",
|
inviteURL: window.discordInviteLink ? (window.pages.Form + "/" + window.code + "/discord/invite") : "",
|
||||||
pinURL: "",
|
pinURL: "",
|
||||||
verifiedURL: "/invite/" + window.code + "/discord/verified/",
|
verifiedURL: window.pages.Form + "/" + window.code + "/discord/verified/",
|
||||||
invalidCodeError: window.messages["errorInvalidPIN"],
|
invalidCodeError: window.messages["errorInvalidPIN"],
|
||||||
accountLinkedError: window.messages["errorAccountLinked"],
|
accountLinkedError: window.messages["errorAccountLinked"],
|
||||||
successError: window.messages["verified"],
|
successError: window.messages["verified"],
|
||||||
@@ -121,8 +121,8 @@ if (window.matrixEnabled) {
|
|||||||
|
|
||||||
const matrixConf: MatrixConfiguration = {
|
const matrixConf: MatrixConfiguration = {
|
||||||
modal: window.matrixModal as Modal,
|
modal: window.matrixModal as Modal,
|
||||||
sendMessageURL: "/invite/" + window.code + "/matrix/user",
|
sendMessageURL: window.pages.Form + "/" + window.code + "/matrix/user",
|
||||||
verifiedURL: "/invite/" + window.code + "/matrix/verified/",
|
verifiedURL: window.pages.Form + "/" + window.code + "/matrix/verified/",
|
||||||
invalidCodeError: window.messages["errorInvalidPIN"],
|
invalidCodeError: window.messages["errorInvalidPIN"],
|
||||||
accountLinkedError: window.messages["errorAccountLinked"],
|
accountLinkedError: window.messages["errorAccountLinked"],
|
||||||
unknownError: window.messages["errorUnknown"],
|
unknownError: window.messages["errorUnknown"],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Modal } from "../modules/modal.js";
|
import { Modal } from "../modules/modal.js";
|
||||||
import { _get, _post, toggleLoader, addLoader, removeLoader } from "../modules/common.js";
|
import { _get, _post, toggleLoader, addLoader, removeLoader } from "../modules/common.js";
|
||||||
|
|
||||||
interface formWindow extends Window {
|
interface formWindow extends GlobalWindow {
|
||||||
invalidPassword: string;
|
invalidPassword: string;
|
||||||
successModal: Modal;
|
successModal: Modal;
|
||||||
telegramModal: Modal;
|
telegramModal: Modal;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { DiscordUser, newDiscordSearch } from "../modules/discord.js";
|
|||||||
import { Search, SearchConfiguration, QueryType, SearchableItem } from "../modules/search.js";
|
import { Search, SearchConfiguration, QueryType, SearchableItem } from "../modules/search.js";
|
||||||
import { HiddenInputField } from "./ui.js";
|
import { HiddenInputField } from "./ui.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
const dateParser = require("any-date-parser");
|
const dateParser = require("any-date-parser");
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { Search, SearchConfiguration, QueryType, SearchableItem } from "../modul
|
|||||||
import { accountURLEvent } from "../modules/accounts.js";
|
import { accountURLEvent } from "../modules/accounts.js";
|
||||||
import { inviteURLEvent } from "../modules/invites.js";
|
import { inviteURLEvent } from "../modules/invites.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export interface activity {
|
export interface activity {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -52,8 +54,8 @@ export class Activity implements activity, SearchableItem {
|
|||||||
link = link.split(split)[0];
|
link = link.split(split)[0];
|
||||||
}
|
}
|
||||||
if (link.slice(-1) != "/") { link += "/"; }
|
if (link.slice(-1) != "/") { link += "/"; }
|
||||||
// FIXME: I should probably just be using window.URLBase, but incase thats not right, i'll put this warning here
|
// FIXME: I should probably just be using window.pages.Base, but incase thats not right, i'll put this warning here
|
||||||
if (link != window.URLBase) console.error(`URL Bases don't match: "${link}" != "${window.URLBase}"`);
|
if (link != window.pages.Base) console.error(`URL Bases don't match: "${link}" != "${window.pages.Base}"`);
|
||||||
return link;
|
return link;
|
||||||
})(); */
|
})(); */
|
||||||
|
|
||||||
@@ -66,17 +68,17 @@ export class Activity implements activity, SearchableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_genUserLink = (): string => {
|
_genUserLink = (): string => {
|
||||||
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-user" data-id="${this._act.user_id}" href="${window.URLBase}/accounts?user=${this._act.user_id}">${this._genUserText()}</a>`;
|
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-user" data-id="${this._act.user_id}" href="${window.pages.Base}${window.pages.Admin}/accounts?user=${this._act.user_id}">${this._genUserText()}</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
_genSrcUserLink = (): string => {
|
_genSrcUserLink = (): string => {
|
||||||
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-user" data-id="${this._act.user_id}" href="${window.URLBase}/accounts?user=${this._act.source}">${this._genSrcUserText()}</a>`;
|
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-user" data-id="${this._act.user_id}" href="${window.pages.Base}${window.pages.Admin}/accounts?user=${this._act.source}">${this._genSrcUserText()}</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderInvText = (): string => { return `<span class="font-medium font-mono">${this.value || this.invite_code || "???"}</span>`; }
|
private _renderInvText = (): string => { return `<span class="font-medium font-mono">${this.value || this.invite_code || "???"}</span>`; }
|
||||||
|
|
||||||
private _genInvLink = (): string => {
|
private _genInvLink = (): string => {
|
||||||
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-invite" data-id="${this.invite_code}" href="${window.URLBase}/?invite=${this.invite_code}">${this._renderInvText()}</a>`;
|
return `<a role="link" tabindex="0" class="hover:underline cursor-pointer activity-pseudo-link-invite" data-id="${this.invite_code}" href="${window.pages.Base}${window.pages.Admin}/?invite=${this.invite_code}">${this._renderInvText()}</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
declare var window: Window;
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export function toDateString(date: Date): string {
|
export function toDateString(date: Date): string {
|
||||||
const locale = window.language || (window as any).navigator.userLanguage || window.navigator.language;
|
const locale = window.language || (window as any).navigator.userLanguage || window.navigator.language;
|
||||||
@@ -23,7 +23,7 @@ export function toDateString(date: Date): string {
|
|||||||
|
|
||||||
export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void => {
|
export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void => {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
if (window.URLBase) { url = window.URLBase + url; }
|
if (window.pages) { url = window.pages.Base + url; }
|
||||||
req.open("GET", url, true);
|
req.open("GET", url, true);
|
||||||
req.responseType = 'json';
|
req.responseType = 'json';
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
@@ -42,7 +42,7 @@ export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHtt
|
|||||||
|
|
||||||
export const _download = (url: string, fname: string): void => {
|
export const _download = (url: string, fname: string): void => {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
if (window.URLBase) { url = window.URLBase + url; }
|
if (window.pages) { url = window.pages.Base + url; }
|
||||||
req.open("GET", url, true);
|
req.open("GET", url, true);
|
||||||
req.responseType = 'blob';
|
req.responseType = 'blob';
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
@@ -58,7 +58,7 @@ export const _download = (url: string, fname: string): void => {
|
|||||||
|
|
||||||
export const _upload = (url: string, formData: FormData): void => {
|
export const _upload = (url: string, formData: FormData): void => {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
if (window.URLBase) { url = window.URLBase + url; }
|
if (window.pages) { url = window.pages.Base + url; }
|
||||||
req.open("POST", url, true);
|
req.open("POST", url, true);
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
// req.setRequestHeader('Content-Type', 'multipart/form-data');
|
// req.setRequestHeader('Content-Type', 'multipart/form-data');
|
||||||
@@ -67,7 +67,8 @@ export const _upload = (url: string, formData: FormData): void => {
|
|||||||
|
|
||||||
export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, response?: boolean, statusHandler?: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void => {
|
export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, response?: boolean, statusHandler?: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void => {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
req.open("POST", window.URLBase + url, true);
|
if (window.pages) { url = window.pages.Base + url; }
|
||||||
|
req.open("POST", url, true);
|
||||||
if (response) {
|
if (response) {
|
||||||
req.responseType = 'json';
|
req.responseType = 'json';
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,8 @@ export const _post = (url: string, data: Object, onreadystatechange: (req: XMLHt
|
|||||||
|
|
||||||
export function _delete(url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void {
|
export function _delete(url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
req.open("DELETE", window.URLBase + url, true);
|
if (window.pages) { url = window.pages.Base + url; }
|
||||||
|
req.open("DELETE", url, true);
|
||||||
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
req.setRequestHeader("Authorization", "Bearer " + window.token);
|
||||||
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||||
req.onreadystatechange = () => {
|
req.onreadystatechange = () => {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import {addLoader, removeLoader, _get} from "../modules/common.js";
|
import {addLoader, removeLoader, _get} from "../modules/common.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export interface DiscordUser {
|
export interface DiscordUser {
|
||||||
name: string;
|
name: string;
|
||||||
avatar_url: string;
|
avatar_url: string;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { _get, _post, _delete, toClipboard, toggleLoader, toDateString } from ".
|
|||||||
import { DiscordUser, newDiscordSearch } from "../modules/discord.js";
|
import { DiscordUser, newDiscordSearch } from "../modules/discord.js";
|
||||||
import { reloadProfileNames } from "../modules/profiles.js";
|
import { reloadProfileNames } from "../modules/profiles.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
class DOMInvite implements Invite {
|
class DOMInvite implements Invite {
|
||||||
updateNotify = (checkbox: HTMLInputElement) => {
|
updateNotify = (checkbox: HTMLInputElement) => {
|
||||||
let state: { [code: string]: { [type: string]: boolean } } = {};
|
let state: { [code: string]: { [type: string]: boolean } } = {};
|
||||||
@@ -66,7 +68,7 @@ class DOMInvite implements Invite {
|
|||||||
codeLink = codeLink.split(split)[0];
|
codeLink = codeLink.split(split)[0];
|
||||||
}
|
}
|
||||||
if (codeLink.slice(-1) != "/") { codeLink += "/"; }
|
if (codeLink.slice(-1) != "/") { codeLink += "/"; }
|
||||||
this._codeLink = codeLink + "invite/" + code;
|
this._codeLink = codeLink + window.pages.Form + "/" + code;
|
||||||
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
|
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
|
||||||
if (this.label == "") {
|
if (this.label == "") {
|
||||||
linkEl.textContent = code.replace(/-/g, '-');
|
linkEl.textContent = code.replace(/-/g, '-');
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
import { Modal } from "../modules/modal.js";
|
import { Modal } from "../modules/modal.js";
|
||||||
import { toggleLoader, _post, unicodeB64Encode } from "../modules/common.js";
|
import { toggleLoader, _post, unicodeB64Encode } from "../modules/common.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export class Login {
|
export class Login {
|
||||||
loggedIn: boolean = false;
|
loggedIn: boolean = false;
|
||||||
private _modal: Modal;
|
private _modal: Modal;
|
||||||
@@ -14,7 +16,7 @@ export class Login {
|
|||||||
|
|
||||||
constructor(modal: Modal, endpoint: string, appearance: string) {
|
constructor(modal: Modal, endpoint: string, appearance: string) {
|
||||||
this._endpoint = endpoint;
|
this._endpoint = endpoint;
|
||||||
this._url = window.URLBase + endpoint;
|
this._url = window.pages.Base + 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;
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
declare var window: Window;
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export class Modal implements Modal {
|
export class Modal implements Modal {
|
||||||
modal: HTMLElement;
|
modal: HTMLElement;
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export class PageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadPage (p: Page) {
|
loadPage (p: Page) {
|
||||||
|
console.log("loading page with", p.name || this.defaultName, p.title, p.url + window.location.search);
|
||||||
window.history.pushState(p.name || this.defaultName, p.title, p.url + window.location.search);
|
window.history.pushState(p.name || this.defaultName, p.title, p.url + window.location.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { _get, _post, _delete, toggleLoader } from "../modules/common.js";
|
import { _get, _post, _delete, toggleLoader } from "../modules/common.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export const profileLoadEvent = new CustomEvent("profileLoadEvent");
|
export const profileLoadEvent = new CustomEvent("profileLoadEvent");
|
||||||
export const reloadProfileNames = (then?: () => void) => _get("/profiles/names", null, (req: XMLHttpRequest) => {
|
export const reloadProfileNames = (then?: () => void) => _get("/profiles/names", null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState != 4) return;
|
if (req.readyState != 4) return;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
const dateParser = require("any-date-parser");
|
const dateParser = require("any-date-parser");
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export interface QueryType {
|
export interface QueryType {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { _get, _post, _delete, _download, _upload, toggleLoader, addLoader, remo
|
|||||||
import { Marked } from "@ts-stack/markdown";
|
import { Marked } from "@ts-stack/markdown";
|
||||||
import { stripMarkdown } from "../modules/stripmd.js";
|
import { stripMarkdown } from "../modules/stripmd.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
const toBool = (s: string): boolean => {
|
const toBool = (s: string): boolean => {
|
||||||
let b = Boolean(s);
|
let b = Boolean(s);
|
||||||
if (s == "false") b = false;
|
if (s == "false") b = false;
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
import { PageManager, Page } from "../modules/pages.js";
|
import { PageManager, Page } from "../modules/pages.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
export interface Tab {
|
export interface Tab {
|
||||||
page: Page;
|
page: Page;
|
||||||
tabEl: HTMLDivElement;
|
tabEl: HTMLDivElement;
|
||||||
@@ -38,7 +40,7 @@ export class Tabs implements Tabs {
|
|||||||
tab.page = {
|
tab.page = {
|
||||||
name: tabID,
|
name: tabID,
|
||||||
title: document.title, /*FIXME: Get actual names from translations*/
|
title: document.title, /*FIXME: Get actual names from translations*/
|
||||||
url: window.URLBase + "/" + url,
|
url: url,
|
||||||
show: () => {
|
show: () => {
|
||||||
tab.buttonEl.classList.add("active", "~urge");
|
tab.buttonEl.classList.add("active", "~urge");
|
||||||
tab.tabEl.classList.remove("unfocused");
|
tab.tabEl.classList.remove("unfocused");
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { _get, _post, toggleLoader, toDateString } from "../modules/common.js";
|
import { _get, _post, toggleLoader, toDateString } from "../modules/common.js";
|
||||||
import { Marked, Renderer } from "@ts-stack/markdown";
|
import { Marked, Renderer } from "@ts-stack/markdown";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
interface updateDTO {
|
interface updateDTO {
|
||||||
new: boolean;
|
new: boolean;
|
||||||
update: Update;
|
update: Update;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { toClipboard, notificationBox } from "./modules/common.js";
|
import { toClipboard, notificationBox } from "./modules/common.js";
|
||||||
|
|
||||||
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
const pin = document.getElementById("pin") as HTMLSpanElement;
|
const pin = document.getElementById("pin") as HTMLSpanElement;
|
||||||
|
|
||||||
if (pin) {
|
if (pin) {
|
||||||
|
|||||||
+1
-2
@@ -3,12 +3,11 @@ import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
|||||||
import { ThemeManager } from "./modules/theme.js";
|
import { ThemeManager } from "./modules/theme.js";
|
||||||
import { PageManager } from "./modules/pages.js";
|
import { PageManager } from "./modules/pages.js";
|
||||||
|
|
||||||
interface sWindow extends Window {
|
interface sWindow extends GlobalWindow {
|
||||||
messages: {};
|
messages: {};
|
||||||
}
|
}
|
||||||
|
|
||||||
declare var window: sWindow;
|
declare var window: sWindow;
|
||||||
window.URLBase = "";
|
|
||||||
|
|
||||||
const theme = new ThemeManager(document.getElementById("button-theme"));
|
const theme = new ThemeManager(document.getElementById("button-theme"));
|
||||||
|
|
||||||
|
|||||||
+14
-2
@@ -12,8 +12,19 @@ interface ArrayConstructor {
|
|||||||
from(arrayLike: any, mapFn?, thisArg?): Array<any>;
|
from(arrayLike: any, mapFn?, thisArg?): Array<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface Window {
|
declare interface PagePaths {
|
||||||
URLBase: string;
|
// The base subfolder the app is hosted on.
|
||||||
|
Base: string;
|
||||||
|
// The subdirectory this bit of the app is hosted on (e.g. admin is usually on "/", myacc is usually on "/my/account")
|
||||||
|
Current: string;
|
||||||
|
// Those for other pages
|
||||||
|
Admin: string;
|
||||||
|
MyAccount: string;
|
||||||
|
Form: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface GlobalWindow extends Window {
|
||||||
|
pages: PagePaths;
|
||||||
modals: Modals;
|
modals: Modals;
|
||||||
cssFile: string;
|
cssFile: string;
|
||||||
availableProfiles: string[];
|
availableProfiles: string[];
|
||||||
@@ -25,6 +36,7 @@ declare interface Window {
|
|||||||
matrixEnabled: boolean;
|
matrixEnabled: boolean;
|
||||||
ombiEnabled: boolean;
|
ombiEnabled: boolean;
|
||||||
jellyseerrEnabled: boolean;
|
jellyseerrEnabled: boolean;
|
||||||
|
pwrEnabled: boolean;
|
||||||
usernameEnabled: boolean;
|
usernameEnabled: boolean;
|
||||||
linkResetEnabled: boolean;
|
linkResetEnabled: boolean;
|
||||||
token: string;
|
token: string;
|
||||||
|
|||||||
+6
-7
@@ -7,7 +7,7 @@ import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration }
|
|||||||
import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.js";
|
import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.js";
|
||||||
import { PageManager } from "./modules/pages.js";
|
import { PageManager } from "./modules/pages.js";
|
||||||
|
|
||||||
interface userWindow extends Window {
|
interface userWindow extends GlobalWindow {
|
||||||
jellyfinID: string;
|
jellyfinID: string;
|
||||||
username: string;
|
username: string;
|
||||||
emailRequired: boolean;
|
emailRequired: boolean;
|
||||||
@@ -18,14 +18,13 @@ interface userWindow extends Window {
|
|||||||
discordInviteLink: boolean;
|
discordInviteLink: boolean;
|
||||||
matrixUserID: string;
|
matrixUserID: string;
|
||||||
discordSendPINMessage: string;
|
discordSendPINMessage: string;
|
||||||
pwrEnabled: string;
|
|
||||||
referralsEnabled: boolean;
|
referralsEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const basePath = window.location.pathname.replace("/password/reset", "");
|
|
||||||
|
|
||||||
declare var window: userWindow;
|
declare var window: userWindow;
|
||||||
|
|
||||||
|
const basePath = window.location.pathname.replace("/password/reset", "");
|
||||||
|
|
||||||
const theme = new ThemeManager(document.getElementById("button-theme"));
|
const theme = new ThemeManager(document.getElementById("button-theme"));
|
||||||
|
|
||||||
window.lang = new lang(window.langFile as LangFile);
|
window.lang = new lang(window.langFile as LangFile);
|
||||||
@@ -38,7 +37,7 @@ window.token = "";
|
|||||||
|
|
||||||
window.modals = {} as Modals;
|
window.modals = {} as Modals;
|
||||||
|
|
||||||
let pages = new PageManager({
|
const pages = new PageManager({
|
||||||
hideOthersOnPageShow: true,
|
hideOthersOnPageShow: true,
|
||||||
defaultName: "",
|
defaultName: "",
|
||||||
defaultTitle: document.title,
|
defaultTitle: document.title,
|
||||||
@@ -311,7 +310,7 @@ class ReferralCard {
|
|||||||
path = path.split(split)[0];
|
path = path.split(split)[0];
|
||||||
}
|
}
|
||||||
if (path.slice(-1) != "/") { path += "/"; }
|
if (path.slice(-1) != "/") { path += "/"; }
|
||||||
path = path + "invite/" + this._code;
|
path = path + window.pages.Form + "/" + this._code;
|
||||||
|
|
||||||
u.pathname = path;
|
u.pathname = path;
|
||||||
u.hash = "";
|
u.hash = "";
|
||||||
@@ -661,7 +660,7 @@ document.addEventListener("details-reload", () => {
|
|||||||
expiryCard.expiry = details.expiry;
|
expiryCard.expiry = details.expiry;
|
||||||
|
|
||||||
const adminBackButton = document.getElementById("admin-back-button") as HTMLAnchorElement;
|
const adminBackButton = document.getElementById("admin-back-button") as HTMLAnchorElement;
|
||||||
adminBackButton.href = window.location.href.replace("my/account", "");
|
adminBackButton.href = window.location.href.replace(window.pages.MyAccount, window.pages.Admin);
|
||||||
|
|
||||||
let messageCard = document.getElementById("card-message");
|
let messageCard = document.getElementById("card-message");
|
||||||
if (details.accounts_admin) {
|
if (details.accounts_admin) {
|
||||||
|
|||||||
+2
-1
@@ -67,7 +67,8 @@ func (app *appContext) getUserTokenLogin(gc *gin.Context) {
|
|||||||
// host := gc.Request.URL.Hostname()
|
// host := gc.Request.URL.Hostname()
|
||||||
host := app.ExternalDomain
|
host := app.ExternalDomain
|
||||||
uri := "/my"
|
uri := "/my"
|
||||||
if strings.HasPrefix(gc.Request.RequestURI, app.URLBase) {
|
// FIXME: This seems like a bad idea? I think it's to deal with people having Reverse proxy subfolder/URL base set to /accounts.
|
||||||
|
if strings.HasPrefix(gc.Request.RequestURI, PAGES.Base) {
|
||||||
uri = "/accounts/my"
|
uri = "/accounts/my"
|
||||||
}
|
}
|
||||||
gc.SetCookie("user-refresh", refresh, REFRESH_TOKEN_VALIDITY_SEC, uri, host, true, true)
|
gc.SetCookie("user-refresh", refresh, REFRESH_TOKEN_VALIDITY_SEC, uri, host, true, true)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (app *appContext) loadCSSHeader() string {
|
|||||||
l := len(css)
|
l := len(css)
|
||||||
h := ""
|
h := ""
|
||||||
for i, f := range css {
|
for i, f := range css {
|
||||||
h += "<" + app.URLBase + "/css/" + f + ">; rel=preload; as=style"
|
h += "<" + PAGES.Base + "/css/" + f + ">; rel=preload; as=style"
|
||||||
if l > 1 && i != (l-1) {
|
if l > 1 && i != (l-1) {
|
||||||
h += ", "
|
h += ", "
|
||||||
}
|
}
|
||||||
@@ -41,18 +41,19 @@ func (app *appContext) loadCSSHeader() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) getURLBase(gc *gin.Context) string {
|
func (app *appContext) getURLBase(gc *gin.Context) string {
|
||||||
if strings.HasPrefix(gc.Request.URL.String(), app.URLBase) {
|
if strings.HasPrefix(gc.Request.URL.String(), PAGES.Base) {
|
||||||
// Hack to fix the common URL base /accounts
|
// Hack to fix the common URL base /accounts
|
||||||
if app.URLBase == "/accounts" && strings.HasPrefix(gc.Request.URL.String(), "/accounts/user/") {
|
if PAGES.Base == "/accounts" && strings.HasPrefix(gc.Request.URL.String(), "/accounts/user/") {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return app.URLBase
|
return PAGES.Base
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func gcHTML(gc *gin.Context, code int, file string, templ gin.H) {
|
func (app *appContext) gcHTML(gc *gin.Context, code int, file string, page Page, templ gin.H) {
|
||||||
gc.Header("Cache-Control", "no-cache")
|
gc.Header("Cache-Control", "no-cache")
|
||||||
|
app.BasePageTemplateValues(gc, page, templ)
|
||||||
gc.HTML(code, file, templ)
|
gc.HTML(code, file, templ)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,16 +62,14 @@ func (app *appContext) pushResources(gc *gin.Context, page Page) {
|
|||||||
switch page {
|
switch page {
|
||||||
case AdminPage:
|
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"}
|
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:
|
case UserPage:
|
||||||
toPush = []string{"/js/user.js", "/js/theme.js", "/js/lang.js", "/js/modal.js", "/js/common.js"}
|
toPush = []string{"/js/user.js", "/js/theme.js", "/js/lang.js", "/js/modal.js", "/js/common.js"}
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
toPush = []string{}
|
toPush = []string{}
|
||||||
}
|
}
|
||||||
if pusher := gc.Writer.Pusher(); pusher != nil {
|
if pusher := gc.Writer.Pusher(); pusher != nil {
|
||||||
for _, f := range toPush {
|
for _, f := range toPush {
|
||||||
if err := pusher.Push(app.URLBase+f, nil); err != nil {
|
if err := pusher.Push(PAGES.Base+f, nil); err != nil {
|
||||||
app.debug.Printf(lm.FailedServerPush, err)
|
app.debug.Printf(lm.FailedServerPush, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,6 +77,48 @@ func (app *appContext) pushResources(gc *gin.Context, page Page) {
|
|||||||
gc.Header("Link", cssHeader)
|
gc.Header("Link", cssHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a gin.H with general values (url base, css version, etc.)
|
||||||
|
func (app *appContext) BasePageTemplateValues(gc *gin.Context, page Page, base gin.H) {
|
||||||
|
set := func(k string, v any) {
|
||||||
|
if _, ok := base[k]; !ok {
|
||||||
|
base[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pages := PagePathsDTO{
|
||||||
|
PagePaths: PAGES,
|
||||||
|
}
|
||||||
|
pages.Base = app.getURLBase(gc)
|
||||||
|
switch page {
|
||||||
|
case AdminPage:
|
||||||
|
pages.Current = PAGES.Admin
|
||||||
|
case FormPage:
|
||||||
|
pages.Current = PAGES.Form
|
||||||
|
case UserPage:
|
||||||
|
pages.Current = PAGES.MyAccount
|
||||||
|
default:
|
||||||
|
pages.Current = "/"
|
||||||
|
}
|
||||||
|
set("pages", pages)
|
||||||
|
ombiEnabled := app.config.Section("ombi").Key("enabled").MustBool(false)
|
||||||
|
jellyseerrEnabled := app.config.Section("jellyseerr").Key("enabled").MustBool(false)
|
||||||
|
notificationsEnabled, _ := app.config.Section("notifications").Key("enabled").Bool()
|
||||||
|
set("notifications", notificationsEnabled)
|
||||||
|
set("cssClass", app.cssClass)
|
||||||
|
set("cssVersion", cssVersion)
|
||||||
|
set("emailEnabled", emailEnabled)
|
||||||
|
set("telegramEnabled", telegramEnabled)
|
||||||
|
set("discordEnabled", discordEnabled)
|
||||||
|
set("matrixEnabled", matrixEnabled)
|
||||||
|
set("ombiEnabled", ombiEnabled)
|
||||||
|
set("jellyseerrEnabled", jellyseerrEnabled)
|
||||||
|
// QUIRK: The login modal html template uses this' existence to check if the modal is for the admin or user page.
|
||||||
|
if page != AdminPage {
|
||||||
|
set("pwrEnabled", app.config.Section("password_resets").Key("enabled").MustBool(false))
|
||||||
|
}
|
||||||
|
set("referralsEnabled", app.config.Section("user_page").Key("enabled").MustBool(false) && app.config.Section("user_page").Key("referrals").MustBool(false))
|
||||||
|
}
|
||||||
|
|
||||||
type Page int
|
type Page int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -132,10 +173,6 @@ 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, AdminPage)
|
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()
|
|
||||||
notificationsEnabled, _ := app.config.Section("notifications").Key("enabled").Bool()
|
|
||||||
ombiEnabled := app.config.Section("ombi").Key("enabled").MustBool(false)
|
|
||||||
jellyseerrEnabled := app.config.Section("jellyseerr").Key("enabled").MustBool(false)
|
|
||||||
jfAdminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
|
jfAdminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
|
||||||
jfAllowAll := app.config.Section("ui").Key("allow_all").MustBool(false)
|
jfAllowAll := app.config.Section("ui").Key("allow_all").MustBool(false)
|
||||||
var license string
|
var license string
|
||||||
@@ -157,19 +194,9 @@ func (app *appContext) AdminPage(gc *gin.Context) {
|
|||||||
builtBy = "???"
|
builtBy = "???"
|
||||||
}
|
}
|
||||||
|
|
||||||
gcHTML(gc, http.StatusOK, "admin.html", gin.H{
|
app.gcHTML(gc, http.StatusOK, "admin.html", AdminPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": "",
|
"contactMessage": "",
|
||||||
"emailEnabled": emailEnabled,
|
|
||||||
"telegramEnabled": telegramEnabled,
|
|
||||||
"discordEnabled": discordEnabled,
|
|
||||||
"matrixEnabled": matrixEnabled,
|
|
||||||
"ombiEnabled": ombiEnabled,
|
|
||||||
"jellyseerrEnabled": jellyseerrEnabled,
|
|
||||||
"linkResetEnabled": app.config.Section("password_resets").Key("link_reset").MustBool(false),
|
"linkResetEnabled": app.config.Section("password_resets").Key("link_reset").MustBool(false),
|
||||||
"notifications": notificationsEnabled,
|
|
||||||
"version": version,
|
"version": version,
|
||||||
"commit": commit,
|
"commit": commit,
|
||||||
"buildTime": buildTime,
|
"buildTime": buildTime,
|
||||||
@@ -186,7 +213,6 @@ func (app *appContext) AdminPage(gc *gin.Context) {
|
|||||||
"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),
|
"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),
|
|
||||||
"loginAppearance": app.config.Section("ui").Key("login_appearance").MustString("clear"),
|
"loginAppearance": app.config.Section("ui").Key("login_appearance").MustString("clear"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -194,25 +220,10 @@ func (app *appContext) AdminPage(gc *gin.Context) {
|
|||||||
func (app *appContext) MyUserPage(gc *gin.Context) {
|
func (app *appContext) MyUserPage(gc *gin.Context) {
|
||||||
app.pushResources(gc, UserPage)
|
app.pushResources(gc, UserPage)
|
||||||
lang := app.getLang(gc, UserPage, app.storage.lang.chosenUserLang)
|
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)
|
|
||||||
jellyseerrEnabled := app.config.Section("jellyseerr").Key("enabled").MustBool(false)
|
|
||||||
data := gin.H{
|
data := gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
"emailEnabled": emailEnabled,
|
|
||||||
"emailRequired": app.config.Section("email").Key("required").MustBool(false),
|
"emailRequired": app.config.Section("email").Key("required").MustBool(false),
|
||||||
"telegramEnabled": telegramEnabled,
|
|
||||||
"discordEnabled": discordEnabled,
|
|
||||||
"matrixEnabled": matrixEnabled,
|
|
||||||
"ombiEnabled": ombiEnabled,
|
|
||||||
"jellyseerrEnabled": jellyseerrEnabled,
|
|
||||||
"pwrEnabled": app.config.Section("password_resets").Key("enabled").MustBool(false),
|
|
||||||
"linkResetEnabled": app.config.Section("password_resets").Key("link_reset").MustBool(false),
|
"linkResetEnabled": app.config.Section("password_resets").Key("link_reset").MustBool(false),
|
||||||
"notifications": notificationsEnabled,
|
|
||||||
"username": !app.config.Section("email").Key("no_username").MustBool(false),
|
"username": !app.config.Section("email").Key("no_username").MustBool(false),
|
||||||
"strings": app.storage.lang.User[lang].Strings,
|
"strings": app.storage.lang.User[lang].Strings,
|
||||||
"validationStrings": app.storage.lang.User[lang].validationStringsJSON,
|
"validationStrings": app.storage.lang.User[lang].validationStringsJSON,
|
||||||
@@ -220,7 +231,6 @@ func (app *appContext) MyUserPage(gc *gin.Context) {
|
|||||||
"langName": lang,
|
"langName": lang,
|
||||||
"jfLink": app.config.Section("ui").Key("redirect_url").String(),
|
"jfLink": app.config.Section("ui").Key("redirect_url").String(),
|
||||||
"requirements": app.validator.getCriteria(),
|
"requirements": app.validator.getCriteria(),
|
||||||
"referralsEnabled": app.config.Section("user_page").Key("enabled").MustBool(false) && app.config.Section("user_page").Key("referrals").MustBool(false),
|
|
||||||
}
|
}
|
||||||
if telegramEnabled {
|
if telegramEnabled {
|
||||||
data["telegramUsername"] = app.telegram.username
|
data["telegramUsername"] = app.telegram.username
|
||||||
@@ -264,7 +274,7 @@ func (app *appContext) MyUserPage(gc *gin.Context) {
|
|||||||
data[name+"MessageContent"] = template.HTML(markdown.ToHTML([]byte(msg.Content), nil, markdownRenderer))
|
data[name+"MessageContent"] = template.HTML(markdown.ToHTML([]byte(msg.Content), nil, markdownRenderer))
|
||||||
}
|
}
|
||||||
|
|
||||||
gcHTML(gc, http.StatusOK, "user.html", data)
|
app.gcHTML(gc, http.StatusOK, "user.html", UserPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) ResetPassword(gc *gin.Context) {
|
func (app *appContext) ResetPassword(gc *gin.Context) {
|
||||||
@@ -278,14 +288,9 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
|||||||
app.pushResources(gc, PWRPage)
|
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),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
"strings": app.storage.lang.PasswordReset[lang].Strings,
|
"strings": app.storage.lang.PasswordReset[lang].Strings,
|
||||||
"success": false,
|
"success": false,
|
||||||
"ombiEnabled": app.config.Section("ombi").Key("enabled").MustBool(false),
|
|
||||||
"jellyseerrEnabled": app.config.Section("jellyseerr").Key("enabled").MustBool(false),
|
|
||||||
"customSuccessCard": false,
|
"customSuccessCard": false,
|
||||||
}
|
}
|
||||||
pwr, isInternal := app.internalPWRs[pin]
|
pwr, isInternal := app.internalPWRs[pin]
|
||||||
@@ -299,6 +304,7 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
|||||||
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.User[lang].validationStringsJSON
|
data["validationStrings"] = app.storage.lang.User[lang].validationStringsJSON
|
||||||
|
// ewwwww, reusing an existing field, FIXME!
|
||||||
data["notifications"] = app.storage.lang.User[lang].notificationsJSON
|
data["notifications"] = app.storage.lang.User[lang].notificationsJSON
|
||||||
data["langName"] = lang
|
data["langName"] = lang
|
||||||
data["passwordReset"] = true
|
data["passwordReset"] = true
|
||||||
@@ -309,10 +315,10 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
|||||||
data["reCAPTCHA"] = app.config.Section("captcha").Key("recaptcha").MustBool(false)
|
data["reCAPTCHA"] = app.config.Section("captcha").Key("recaptcha").MustBool(false)
|
||||||
data["reCAPTCHASiteKey"] = app.config.Section("captcha").Key("recaptcha_site_key").MustString("")
|
data["reCAPTCHASiteKey"] = app.config.Section("captcha").Key("recaptcha_site_key").MustString("")
|
||||||
data["pwrPIN"] = pin
|
data["pwrPIN"] = pin
|
||||||
gcHTML(gc, http.StatusOK, "form-loader.html", data)
|
app.gcHTML(gc, http.StatusOK, "form-loader.html", PWRPage, data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer gcHTML(gc, http.StatusOK, "password-reset.html", data)
|
defer app.gcHTML(gc, http.StatusOK, "password-reset.html", PWRPage, data)
|
||||||
// If it's a bot, pretend to be a success so the preview is nice.
|
// If it's a bot, pretend to be a success so the preview is nice.
|
||||||
if isBot {
|
if isBot {
|
||||||
app.debug.Println(lm.IgnoreBotPWR)
|
app.debug.Println(lm.IgnoreBotPWR)
|
||||||
@@ -413,10 +419,7 @@ func (app *appContext) GetCaptcha(gc *gin.Context) {
|
|||||||
if !isPWR {
|
if !isPWR {
|
||||||
inv, ok = app.storage.GetInvitesKey(code)
|
inv, ok = app.storage.GetInvitesKey(code)
|
||||||
if !ok {
|
if !ok {
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
app.gcHTML(gc, 404, "invalidCode.html", OtherPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -453,10 +456,7 @@ func (app *appContext) GenCaptcha(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
app.gcHTML(gc, 404, "invalidCode.html", OtherPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -587,10 +587,7 @@ func (app *appContext) VerifyCaptcha(gc *gin.Context) {
|
|||||||
if !isPWR {
|
if !isPWR {
|
||||||
inv, ok = app.storage.GetInvitesKey(code)
|
inv, ok = app.storage.GetInvitesKey(code)
|
||||||
if !ok {
|
if !ok {
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
app.gcHTML(gc, 404, "invalidCode.html", OtherPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -617,10 +614,7 @@ func (app *appContext) VerifyCaptcha(gc *gin.Context) {
|
|||||||
|
|
||||||
func (app *appContext) NewUserFromConfirmationKey(invite Invite, key string, lang string, gc *gin.Context) {
|
func (app *appContext) NewUserFromConfirmationKey(invite Invite, key string, lang string, gc *gin.Context) {
|
||||||
fail := func() {
|
fail := func() {
|
||||||
gcHTML(gc, 404, "404.html", gin.H{
|
app.gcHTML(gc, 404, "404.html", OtherPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -691,10 +685,7 @@ func (app *appContext) NewUserFromConfirmationKey(invite Invite, key string, lan
|
|||||||
if app.config.Section("ui").Key("auto_redirect").MustBool(false) {
|
if app.config.Section("ui").Key("auto_redirect").MustBool(false) {
|
||||||
gc.Redirect(301, jfLink)
|
gc.Redirect(301, jfLink)
|
||||||
} else {
|
} else {
|
||||||
gcHTML(gc, http.StatusOK, "create-success.html", gin.H{
|
app.gcHTML(gc, http.StatusOK, "create-success.html", OtherPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"strings": app.storage.lang.User[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(),
|
||||||
@@ -725,10 +716,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
|
|||||||
// if app.checkInvite(code, false, "") {
|
// if app.checkInvite(code, false, "") {
|
||||||
invite, ok := app.storage.GetInvitesKey(gc.Param("invCode"))
|
invite, ok := app.storage.GetInvitesKey(gc.Param("invCode"))
|
||||||
if !ok {
|
if !ok {
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
app.gcHTML(gc, 404, "invalidCode.html", FormPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -747,7 +735,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
|
|||||||
discord := discordEnabled && app.config.Section("discord").Key("show_on_reg").MustBool(true)
|
discord := discordEnabled && app.config.Section("discord").Key("show_on_reg").MustBool(true)
|
||||||
matrix := matrixEnabled && app.config.Section("matrix").Key("show_on_reg").MustBool(true)
|
matrix := matrixEnabled && app.config.Section("matrix").Key("show_on_reg").MustBool(true)
|
||||||
|
|
||||||
userPageAddress := fmt.Sprintf("%s/my/account", app.ExternalURI)
|
userPageAddress := app.ExternalURI + PAGES.MyAccount
|
||||||
|
|
||||||
fromUser := ""
|
fromUser := ""
|
||||||
if invite.ReferrerJellyfinID != "" {
|
if invite.ReferrerJellyfinID != "" {
|
||||||
@@ -758,9 +746,6 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := gin.H{
|
data := gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
"helpMessage": app.config.Section("ui").Key("help_message").String(),
|
"helpMessage": app.config.Section("ui").Key("help_message").String(),
|
||||||
"successMessage": app.config.Section("ui").Key("success_message").String(),
|
"successMessage": app.config.Section("ui").Key("success_message").String(),
|
||||||
@@ -772,6 +757,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
|
|||||||
"username": !app.config.Section("email").Key("no_username").MustBool(false),
|
"username": !app.config.Section("email").Key("no_username").MustBool(false),
|
||||||
"strings": app.storage.lang.User[lang].Strings,
|
"strings": app.storage.lang.User[lang].Strings,
|
||||||
"validationStrings": app.storage.lang.User[lang].validationStringsJSON,
|
"validationStrings": app.storage.lang.User[lang].validationStringsJSON,
|
||||||
|
// ewwwww, reusing an existing field, FIXME!
|
||||||
"notifications": app.storage.lang.User[lang].notificationsJSON,
|
"notifications": app.storage.lang.User[lang].notificationsJSON,
|
||||||
"code": invite.Code,
|
"code": invite.Code,
|
||||||
"confirmation": app.config.Section("email_confirmation").Key("enabled").MustBool(false),
|
"confirmation": app.config.Section("email_confirmation").Key("enabled").MustBool(false),
|
||||||
@@ -837,15 +823,12 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
|
|||||||
// pin := ""
|
// pin := ""
|
||||||
// for _, token := range app.discord.tokens {
|
// for _, token := range app.discord.tokens {
|
||||||
// if
|
// if
|
||||||
gcHTML(gc, http.StatusOK, "form-loader.html", data)
|
app.gcHTML(gc, http.StatusOK, "form-loader.html", OtherPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) NoRouteHandler(gc *gin.Context) {
|
func (app *appContext) NoRouteHandler(gc *gin.Context) {
|
||||||
app.pushResources(gc, OtherPage)
|
app.pushResources(gc, OtherPage)
|
||||||
gcHTML(gc, 404, "404.html", gin.H{
|
app.gcHTML(gc, 404, "404.html", OtherPage, gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user