form/admin: don't allow "+" in username/email

Jellyfin doesn't like this.
pull/297/head
Harvey Tindall 3 months ago
parent a7aa3fd53e
commit 6c30a1ff40
No known key found for this signature in database
GPG Key ID: BBC65952848FB1A2

@ -196,7 +196,7 @@ STATIC_TARGET = $(STATIC_SRC:static/%=$(DATA)/web/%)
COPY_SRC = images/banner.svg jfa-go.service LICENSE $(LANG_SRC) $(STATIC_SRC) COPY_SRC = images/banner.svg jfa-go.service LICENSE $(LANG_SRC) $(STATIC_SRC)
COPY_TARGET = $(DATA)/jfa-go.service COPY_TARGET = $(DATA)/jfa-go.service
# $(DATA)/LICENSE $(LANG_TARGET) $(STATIC_TARGET) $(DATA)/web/css/$(CSSVERSION)bundle.css # $(DATA)/LICENSE $(LANG_TARGET) $(STATIC_TARGET) $(DATA)/web/css/$(CSSVERSION)bundle.css
$(COPY_TARGET): $(INLINE_TARGET) $(STATIC_SRC) $(COPY_TARGET): $(INLINE_TARGET) $(STATIC_SRC) $(LANG_SRC)
$(info copying crash page) $(info copying crash page)
cp $(DATA)/crash.html $(DATA)/html/ cp $(DATA)/crash.html $(DATA)/html/
$(info copying static data) $(info copying static data)

@ -48,7 +48,8 @@
"errorConnection": "Couldn't connect to jfa-go.", "errorConnection": "Couldn't connect to jfa-go.",
"errorUnknown": "Unknown error.", "errorUnknown": "Unknown error.",
"error401Unauthorized": "Unauthorized. Try refreshing the page.", "error401Unauthorized": "Unauthorized. Try refreshing the page.",
"errorSaveSettings": "Couldn't save settings." "errorSaveSettings": "Couldn't save settings.",
"errorSpecialSymbols": "Field cannot contain special symbols."
}, },
"quantityStrings": { "quantityStrings": {
"year": { "year": {

@ -52,6 +52,14 @@ func lshortfile() string {
return Lshortfile(3) return Lshortfile(3)
} }
func LshortfileTree() string {
out := ""
for i := 6; i >= 0; i-- {
out += strconv.Itoa(i) + ":" + Lshortfile(i) + " "
}
return out
}
func NewLogger(out io.Writer, prefix string, flag int, color c.Attribute) (l *Logger) { func NewLogger(out io.Writer, prefix string, flag int, color c.Attribute) (l *Logger) {
l = &Logger{} l = &Logger{}
// Use reimplemented Lshortfile since wrapping the log functions messes them up // Use reimplemented Lshortfile since wrapping the log functions messes them up
@ -96,6 +104,13 @@ func (l *Logger) PrintfCustomLevel(level int, format string, v ...interface{}) {
l.logger.Print(out) l.logger.Print(out)
} }
func (l *Logger) PrintfNoFile(format string, v ...interface{}) {
if l.empty {
return
}
l.logger.Print(l.printer.Sprintf(format, v...))
}
func (l *Logger) Print(v ...interface{}) { func (l *Logger) Print(v ...interface{}) {
if l.empty { if l.empty {
return return

@ -175,6 +175,7 @@ const (
AccountLinked = "account already linked and require_unique enabled" AccountLinked = "account already linked and require_unique enabled"
AccountUnverified = "unverified" AccountUnverified = "unverified"
FailedSetDiscordMemberRole = "Failed to apply/remove " + Discord + " member role: %v" FailedSetDiscordMemberRole = "Failed to apply/remove " + Discord + " member role: %v"
InvalidChar = "Invalid character '%c'"
FailedSetEmailAddress = "Failed to set email address for %s user \"%s\": %v" FailedSetEmailAddress = "Failed to set email address for %s user \"%s\": %v"

@ -6,7 +6,8 @@ import (
type stringResponse struct { type stringResponse struct {
Response string `json:"response" example:"message"` Response string `json:"response" example:"message"`
Error string `json:"error" example:"errorDescription"` ErrorText string `json:"error" example:"No special symbols allowed."`
ErrorCode string `json:"error_code" example:"errorSpecialSymbols"`
} }
type boolResponse struct { type boolResponse struct {

@ -176,13 +176,32 @@ const rePasswordField = document.getElementById("create-reenter-password") as HT
let captcha = new Captcha(window.code, window.captcha, window.reCAPTCHA, false); let captcha = new Captcha(window.code, window.captcha, window.reCAPTCHA, false);
const clearSubmitButton = () => {
submitInput.setCustomValidity("");
submitSpan.title = "";
};
const invalidMessage = (el: HTMLInputElement, msg: string) => {
el.setCustomValidity(msg);
submitInput.setCustomValidity(msg);
submitSpan.title = msg;
};
function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: boolean): void { function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: boolean): void {
clearSubmitButton();
if (window.emailRequired) { if (window.emailRequired) {
if (!emailField.value.includes("@")) { if (!emailField.value.includes("@")) {
oncomplete(false); oncomplete(false);
return; return;
} }
} }
usernameField.setCustomValidity("");
// Jellyfin doesn't like having "+" in the username field
if (usernameField.value.includes("+")) {
invalidMessage(usernameField, window.messages["errorSpecialSymbols"]);
oncomplete(false);
return;
}
if (window.discordEnabled && window.discordRequired && !discordVerified) { if (window.discordEnabled && window.discordRequired && !discordVerified) {
oncomplete(false); oncomplete(false);
return; return;

@ -1138,7 +1138,12 @@ export class accountsList {
console.log("User created, but welcome email failed"); console.log("User created, but welcome email failed");
} }
} else { } else {
window.notifications.customError("addUser", window.lang.var("notifications", "errorUserCreated", `"${send['username']}"`)); let msg = window.lang.var("notifications", "errorUserCreated", `"${send['username']}"`);
if ("error" in req.response) {
let realError = window.lang.notif(req.response["error"]);
if (realError) msg = realError;
}
window.notifications.customError("addUser", msg);
} }
if (req.response["error"] as String) { if (req.response["error"] as String) {
console.log(req.response["error"]); console.log(req.response["error"]);

@ -1,10 +1,13 @@
package main package main
import ( import (
"fmt"
"strings"
"sync" "sync"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/hrfee/jfa-go/logger"
lm "github.com/hrfee/jfa-go/logmessages" lm "github.com/hrfee/jfa-go/logmessages"
"github.com/hrfee/mediabrowser" "github.com/hrfee/mediabrowser"
"github.com/lithammer/shortuuid/v3" "github.com/lithammer/shortuuid/v3"
@ -53,9 +56,11 @@ type NewUserData struct {
func (app *appContext) NewUserPostVerification(p NewUserParams) (out NewUserData, pendingTasks *sync.WaitGroup) { func (app *appContext) NewUserPostVerification(p NewUserParams) (out NewUserData, pendingTasks *sync.WaitGroup) {
pendingTasks = &sync.WaitGroup{} pendingTasks = &sync.WaitGroup{}
// Some helper functions which will behave as our app.info/error/debug // Some helper functions which will behave as our app.info/error/debug
// And make sure we capture the correct caller location.
deferLogInfo := func(s string, args ...any) { deferLogInfo := func(s string, args ...any) {
loc := logger.Lshortfile(2)
out.Log = func() { out.Log = func() {
app.info.Printf(s, args) app.info.PrintfNoFile(loc+" "+s, args...)
} }
} }
/* deferLogDebug := func(s string, args ...any) { /* deferLogDebug := func(s string, args ...any) {
@ -64,11 +69,19 @@ func (app *appContext) NewUserPostVerification(p NewUserParams) (out NewUserData
} }
} */ } */
deferLogError := func(s string, args ...any) { deferLogError := func(s string, args ...any) {
loc := logger.Lshortfile(2)
out.Log = func() { out.Log = func() {
app.err.Printf(s, args) app.err.PrintfNoFile(loc+" "+s, args...)
} }
} }
if strings.ContainsRune(p.Req.Username, '+') {
deferLogError(lm.FailedCreateUser, lm.Jellyfin, p.Req.Username, fmt.Sprintf(lm.InvalidChar, '+'))
out.Status = 400
out.Message = "errorSpecialSymbols"
return
}
existingUser, _ := app.jf.UserByName(p.Req.Username, false) existingUser, _ := app.jf.UserByName(p.Req.Username, false)
if existingUser.Name != "" { if existingUser.Name != "" {
out.Message = lm.UserExists out.Message = lm.UserExists

@ -677,7 +677,7 @@ func (app *appContext) NewUserFromConfirmationKey(invite Invite, key string, lan
nu.Log() nu.Log()
} }
if !nu.Created { if !nu.Created {
respond(nu.Status, nu.Message, gc) // respond(nu.Status, nu.Message, gc)
fail() fail()
return return
} }

Loading…
Cancel
Save