2020-08-01 23:05:35 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-01-25 21:26:54 +00:00
|
|
|
"encoding/json"
|
2021-02-01 17:39:19 +00:00
|
|
|
"io/fs"
|
2021-01-25 21:26:54 +00:00
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
2020-08-01 23:05:35 +00:00
|
|
|
"github.com/gin-gonic/gin"
|
2023-10-19 16:19:52 +00:00
|
|
|
"github.com/hrfee/jfa-go/easyproxy"
|
2024-08-01 19:17:05 +00:00
|
|
|
lm "github.com/hrfee/jfa-go/logmessages"
|
2021-03-29 20:49:46 +00:00
|
|
|
"github.com/hrfee/mediabrowser"
|
2020-08-01 23:05:35 +00:00
|
|
|
)
|
|
|
|
|
2021-01-25 21:26:54 +00:00
|
|
|
func (app *appContext) ServeSetup(gc *gin.Context) {
|
|
|
|
lang := gc.Query("lang")
|
|
|
|
if lang == "" {
|
|
|
|
lang = "en-us"
|
|
|
|
} else if _, ok := app.storage.lang.Admin[lang]; !ok {
|
|
|
|
lang = "en-us"
|
|
|
|
}
|
|
|
|
emailLang := lang
|
|
|
|
if _, ok := app.storage.lang.Email[lang]; !ok {
|
|
|
|
emailLang = "en-us"
|
|
|
|
}
|
2021-01-26 22:57:29 +00:00
|
|
|
|
|
|
|
messages := map[string]map[string]string{
|
|
|
|
"ui": {
|
|
|
|
"contact_message": app.config.Section("ui").Key("contact_message").String(),
|
|
|
|
"help_message": app.config.Section("ui").Key("help_message").String(),
|
|
|
|
"success_message": app.config.Section("ui").Key("success_message").String(),
|
|
|
|
},
|
2021-06-23 14:44:48 +00:00
|
|
|
"messages": {
|
2021-05-07 20:53:29 +00:00
|
|
|
"message": app.config.Section("messages").Key("message").String(),
|
2021-01-26 22:57:29 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
msg, err := json.Marshal(messages)
|
|
|
|
if err != nil {
|
|
|
|
respond(500, "Failed to fetch default values", gc)
|
|
|
|
return
|
|
|
|
}
|
2021-01-27 21:37:43 +00:00
|
|
|
gc.HTML(200, "setup.html", gin.H{
|
2022-01-09 19:29:17 +00:00
|
|
|
"cssVersion": cssVersion,
|
|
|
|
"lang": app.storage.lang.Setup[lang],
|
2024-10-11 16:08:14 +00:00
|
|
|
"strings": app.storage.lang.Setup[lang].Strings,
|
2022-01-09 19:29:17 +00:00
|
|
|
"emailLang": app.storage.lang.Email[emailLang],
|
|
|
|
"language": app.storage.lang.Setup[lang].JSON,
|
|
|
|
"messages": string(msg),
|
2021-01-25 21:26:54 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-08-01 23:05:35 +00:00
|
|
|
type testReq struct {
|
2023-10-19 16:19:52 +00:00
|
|
|
ServerType string `json:"type"`
|
|
|
|
Server string `json:"server"`
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
Proxy bool `json:"proxy"`
|
|
|
|
ProxyProtocol string `json:"proxy_protocol,omitempty"`
|
|
|
|
ProxyAddress string `json:"proxy_address,omitempty"`
|
|
|
|
ProxyUsername string `json:"proxy_user,omitempty"`
|
|
|
|
ProxyPassword string `json:"proxy_password,omitempty"`
|
2020-08-01 23:05:35 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 12:36:54 +00:00
|
|
|
func (app *appContext) TestJF(gc *gin.Context) {
|
2020-08-01 23:05:35 +00:00
|
|
|
var req testReq
|
|
|
|
gc.BindJSON(&req)
|
2021-07-24 13:15:10 +00:00
|
|
|
if !(strings.HasPrefix(req.Server, "http://") || strings.HasPrefix(req.Server, "https://")) {
|
|
|
|
req.Server = "http://" + req.Server
|
|
|
|
}
|
2021-01-27 12:55:39 +00:00
|
|
|
serverType := mediabrowser.JellyfinServer
|
|
|
|
if req.ServerType == "emby" {
|
|
|
|
serverType = mediabrowser.EmbyServer
|
|
|
|
}
|
2021-03-29 19:57:13 +00:00
|
|
|
tempjf, _ := mediabrowser.NewServer(serverType, req.Server, "jfa-go-setup", app.version, "auth", "auth", mediabrowser.NewNamedTimeoutHandler("authJF", req.Server, true), 30)
|
2023-10-19 16:19:52 +00:00
|
|
|
|
|
|
|
if req.Proxy {
|
|
|
|
conf := easyproxy.ProxyConfig{
|
|
|
|
Protocol: easyproxy.HTTP,
|
|
|
|
Addr: req.ProxyAddress,
|
|
|
|
User: req.ProxyUsername,
|
|
|
|
Password: req.ProxyPassword,
|
|
|
|
}
|
|
|
|
if strings.Contains(req.ProxyProtocol, "socks") {
|
|
|
|
conf.Protocol = easyproxy.SOCKS5
|
|
|
|
}
|
|
|
|
|
|
|
|
transport, err := easyproxy.NewTransport(conf)
|
|
|
|
if err != nil {
|
|
|
|
respond(400, "errorProxy", gc)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tempjf.SetTransport(transport)
|
|
|
|
}
|
|
|
|
|
2024-08-06 13:48:31 +00:00
|
|
|
user, err := tempjf.Authenticate(req.Username, req.Password)
|
|
|
|
if err != nil {
|
2021-07-24 13:15:10 +00:00
|
|
|
msg := ""
|
2024-08-06 13:48:31 +00:00
|
|
|
status := 500
|
|
|
|
switch err.(type) {
|
|
|
|
case mediabrowser.ErrUnauthorized:
|
2021-07-24 13:15:10 +00:00
|
|
|
msg = "errorInvalidUserPass"
|
2024-08-06 13:48:31 +00:00
|
|
|
status = 401
|
|
|
|
case mediabrowser.ErrForbidden:
|
2021-07-24 13:15:10 +00:00
|
|
|
msg = "errorUserDisabled"
|
2024-08-06 13:48:31 +00:00
|
|
|
status = 403
|
|
|
|
case mediabrowser.ErrNotFound:
|
2021-07-24 13:15:10 +00:00
|
|
|
msg = "error404"
|
2024-08-06 13:48:31 +00:00
|
|
|
status = 404
|
|
|
|
default:
|
|
|
|
msg = "errorConnectionRefused"
|
2021-07-24 13:15:10 +00:00
|
|
|
}
|
2024-08-01 19:17:05 +00:00
|
|
|
app.err.Printf(lm.FailedAuthJellyfin, req.Server, status, err)
|
2021-07-24 13:15:10 +00:00
|
|
|
if msg != "" {
|
|
|
|
respond(status, msg, gc)
|
|
|
|
} else {
|
|
|
|
respondBool(status, false, gc)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !user.Policy.IsAdministrator {
|
|
|
|
respond(403, "errorNotAdmin", gc)
|
2020-08-01 23:05:35 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
gc.JSON(200, map[string]bool{"success": true})
|
|
|
|
}
|
2021-01-25 21:26:54 +00:00
|
|
|
|
2021-02-01 17:39:19 +00:00
|
|
|
// The first filesystem passed should be the localFS, to ensure the local lang files are loaded first.
|
|
|
|
func (st *Storage) loadLangSetup(filesystems ...fs.FS) error {
|
2021-01-25 21:26:54 +00:00
|
|
|
st.lang.Setup = map[string]setupLang{}
|
|
|
|
var english setupLang
|
2021-04-13 17:34:13 +00:00
|
|
|
loadedLangs := make([]map[string]bool, len(filesystems))
|
|
|
|
var load loadLangFunc
|
|
|
|
load = func(fsIndex int, fname string) error {
|
|
|
|
filesystem := filesystems[fsIndex]
|
2021-01-25 21:26:54 +00:00
|
|
|
index := strings.TrimSuffix(fname, filepath.Ext(fname))
|
|
|
|
lang := setupLang{}
|
2021-02-08 12:03:22 +00:00
|
|
|
f, err := fs.ReadFile(filesystem, FSJoin(st.lang.SetupPath, fname))
|
2021-01-25 21:26:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = json.Unmarshal(f, &lang)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-06-16 17:29:49 +00:00
|
|
|
st.lang.Common.patchCommonStrings(&lang.Strings, index)
|
|
|
|
st.lang.Common.patchCommonNotifications(&lang.Notifications, index)
|
2021-01-25 21:26:54 +00:00
|
|
|
if fname != "en-us.json" {
|
2021-04-13 17:34:13 +00:00
|
|
|
if lang.Meta.Fallback != "" {
|
|
|
|
fallback, ok := st.lang.Setup[lang.Meta.Fallback]
|
|
|
|
err = nil
|
|
|
|
if !ok {
|
|
|
|
err = load(fsIndex, lang.Meta.Fallback+".json")
|
|
|
|
fallback = st.lang.Setup[lang.Meta.Fallback]
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
loadedLangs[fsIndex][lang.Meta.Fallback+".json"] = true
|
|
|
|
patchLang(&lang.Strings, &fallback.Strings, &english.Strings)
|
|
|
|
patchLang(&lang.StartPage, &fallback.StartPage, &english.StartPage)
|
2024-08-04 18:03:00 +00:00
|
|
|
patchLang(&lang.EndPage, &fallback.EndPage, &english.EndPage)
|
|
|
|
patchLang(&lang.General, &fallback.General, &english.General)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Updates, &fallback.Updates, &english.Updates)
|
2023-10-19 16:19:52 +00:00
|
|
|
patchLang(&lang.Proxy, &fallback.Proxy, &english.Proxy)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Language, &fallback.Language, &english.Language)
|
|
|
|
patchLang(&lang.Login, &fallback.Login, &english.Login)
|
|
|
|
patchLang(&lang.JellyfinEmby, &fallback.JellyfinEmby, &english.JellyfinEmby)
|
2024-08-04 18:03:00 +00:00
|
|
|
patchLang(&lang.Ombi, &fallback.Ombi, &english.Ombi)
|
|
|
|
patchLang(&lang.Jellyseerr, &fallback.Jellyseerr, &english.Jellyseerr)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Email, &fallback.Email, &english.Email)
|
2021-06-23 14:44:48 +00:00
|
|
|
patchLang(&lang.Messages, &fallback.Messages, &english.Messages)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Notifications, &fallback.Notifications, &english.Notifications)
|
2023-06-26 20:29:49 +00:00
|
|
|
patchLang(&lang.UserPage, &fallback.UserPage, &english.UserPage)
|
2024-08-04 18:03:00 +00:00
|
|
|
patchLang(&lang.WelcomeEmails, &fallback.WelcomeEmails, &english.WelcomeEmails)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.PasswordResets, &fallback.PasswordResets, &english.PasswordResets)
|
|
|
|
patchLang(&lang.InviteEmails, &fallback.InviteEmails, &english.InviteEmails)
|
|
|
|
patchLang(&lang.PasswordValidation, &fallback.PasswordValidation, &english.PasswordValidation)
|
|
|
|
patchLang(&lang.HelpMessages, &fallback.HelpMessages, &english.HelpMessages)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lang.Meta.Fallback != "" && err != nil) || lang.Meta.Fallback == "" {
|
|
|
|
patchLang(&lang.Strings, &english.Strings)
|
|
|
|
patchLang(&lang.StartPage, &english.StartPage)
|
2024-08-04 18:03:00 +00:00
|
|
|
patchLang(&lang.EndPage, &english.EndPage)
|
|
|
|
patchLang(&lang.General, &english.General)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Updates, &english.Updates)
|
2023-10-19 16:19:52 +00:00
|
|
|
patchLang(&lang.Proxy, &english.Proxy)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Language, &english.Language)
|
|
|
|
patchLang(&lang.Login, &english.Login)
|
|
|
|
patchLang(&lang.JellyfinEmby, &english.JellyfinEmby)
|
2024-08-04 18:03:00 +00:00
|
|
|
patchLang(&lang.Ombi, &english.Ombi)
|
|
|
|
patchLang(&lang.Jellyseerr, &english.Jellyseerr)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Email, &english.Email)
|
2021-12-31 17:49:25 +00:00
|
|
|
patchLang(&lang.Messages, &english.Messages)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.Notifications, &english.Notifications)
|
2023-06-26 20:29:49 +00:00
|
|
|
patchLang(&lang.UserPage, &english.UserPage)
|
2024-08-04 18:03:00 +00:00
|
|
|
patchLang(&lang.WelcomeEmails, &english.WelcomeEmails)
|
2021-04-13 17:34:13 +00:00
|
|
|
patchLang(&lang.PasswordResets, &english.PasswordResets)
|
|
|
|
patchLang(&lang.InviteEmails, &english.InviteEmails)
|
|
|
|
patchLang(&lang.PasswordValidation, &english.PasswordValidation)
|
|
|
|
patchLang(&lang.HelpMessages, &english.HelpMessages)
|
|
|
|
}
|
2021-01-25 21:26:54 +00:00
|
|
|
}
|
2021-01-26 22:57:29 +00:00
|
|
|
stringSettings, err := json.Marshal(lang)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
lang.JSON = string(stringSettings)
|
2021-01-25 21:26:54 +00:00
|
|
|
st.lang.Setup[index] = lang
|
|
|
|
return nil
|
|
|
|
}
|
2021-02-01 17:39:19 +00:00
|
|
|
engFound := false
|
|
|
|
var err error
|
2021-04-13 17:34:13 +00:00
|
|
|
for i := range filesystems {
|
|
|
|
loadedLangs[i] = map[string]bool{}
|
|
|
|
err = load(i, "en-us.json")
|
2021-02-01 17:39:19 +00:00
|
|
|
if err == nil {
|
|
|
|
engFound = true
|
|
|
|
}
|
2021-04-13 17:34:13 +00:00
|
|
|
loadedLangs[i]["en-us.json"] = true
|
2021-01-25 21:26:54 +00:00
|
|
|
}
|
2021-02-01 17:39:19 +00:00
|
|
|
if !engFound {
|
2021-01-25 21:26:54 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-02-01 17:39:19 +00:00
|
|
|
english = st.lang.Setup["en-us"]
|
2021-02-01 18:41:45 +00:00
|
|
|
setupLoaded := false
|
2021-04-13 17:34:13 +00:00
|
|
|
for i := range filesystems {
|
|
|
|
files, err := fs.ReadDir(filesystems[i], st.lang.SetupPath)
|
2021-02-01 17:39:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, f := range files {
|
2021-04-13 17:34:13 +00:00
|
|
|
if !loadedLangs[i][f.Name()] {
|
|
|
|
err = load(i, f.Name())
|
2021-02-01 18:41:45 +00:00
|
|
|
if err == nil {
|
|
|
|
setupLoaded = true
|
2021-04-13 17:34:13 +00:00
|
|
|
loadedLangs[i][f.Name()] = true
|
2021-02-01 17:39:19 +00:00
|
|
|
}
|
2021-01-25 21:26:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-01 18:41:45 +00:00
|
|
|
if !setupLoaded {
|
|
|
|
return err
|
|
|
|
}
|
2021-01-25 21:26:54 +00:00
|
|
|
return nil
|
|
|
|
}
|