mirror of
https://github.com/unmojang/drasl.git
synced 2025-09-07 22:25:03 -04:00
cleanup
This commit is contained in:
parent
57d98fb41c
commit
fc38f38e48
16
api.go
16
api.go
@ -121,20 +121,20 @@ func (app *App) APIRequestToMaybeUser(c echo.Context) (mo.Option[User], error) {
|
|||||||
|
|
||||||
tokenMatch := bearerExp.FindStringSubmatch(authorizationHeader)
|
tokenMatch := bearerExp.FindStringSubmatch(authorizationHeader)
|
||||||
if tokenMatch == nil || len(tokenMatch) < 2 {
|
if tokenMatch == nil || len(tokenMatch) < 2 {
|
||||||
return mo.None[User](), NewUserError(http.StatusUnauthorized, "Malformed Authorization header")
|
return mo.None[User](), NewUserErrorWithCode(http.StatusUnauthorized, "Malformed Authorization header")
|
||||||
}
|
}
|
||||||
token := tokenMatch[1]
|
token := tokenMatch[1]
|
||||||
|
|
||||||
var user User
|
var user User
|
||||||
if err := app.DB.First(&user, "api_token = ?", token).Error; err != nil {
|
if err := app.DB.First(&user, "api_token = ?", token).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return mo.None[User](), NewUserError(http.StatusUnauthorized, "Unknown API token")
|
return mo.None[User](), NewUserErrorWithCode(http.StatusUnauthorized, "Unknown API token")
|
||||||
}
|
}
|
||||||
return mo.None[User](), err
|
return mo.None[User](), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsLocked {
|
if user.IsLocked {
|
||||||
return mo.None[User](), NewUserError(http.StatusForbidden, "Account is locked")
|
return mo.None[User](), NewUserErrorWithCode(http.StatusForbidden, "Account is locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
return mo.Some(user), nil
|
return mo.Some(user), nil
|
||||||
@ -147,7 +147,7 @@ func (app *App) withAPIToken(requireLogin bool, f func(c echo.Context, user *Use
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if maybeUser.IsAbsent() && requireLogin {
|
if maybeUser.IsAbsent() && requireLogin {
|
||||||
return NewUserError(http.StatusUnauthorized, "Route requires authorization. Missing 'Bearer: abcdef' Authorization header")
|
return NewUserErrorWithCode(http.StatusUnauthorized, "Route requires authorization. Missing 'Bearer: abcdef' Authorization header")
|
||||||
}
|
}
|
||||||
return f(c, maybeUser.ToPointer())
|
return f(c, maybeUser.ToPointer())
|
||||||
}
|
}
|
||||||
@ -345,7 +345,7 @@ func (app *App) APIGetUser() func(c echo.Context) error {
|
|||||||
uuidParam := c.Param("uuid")
|
uuidParam := c.Param("uuid")
|
||||||
if uuidParam != "" {
|
if uuidParam != "" {
|
||||||
if !caller.IsAdmin && (caller.UUID != uuidParam) {
|
if !caller.IsAdmin && (caller.UUID != uuidParam) {
|
||||||
return NewUserError(http.StatusForbidden, "You are not authorized to access that user.")
|
return NewUserErrorWithCode(http.StatusForbidden, "You are not authorized to access that user.")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := uuid.Parse(uuidParam)
|
_, err := uuid.Parse(uuidParam)
|
||||||
@ -523,7 +523,7 @@ func (app *App) APIUpdateUser() func(c echo.Context) error {
|
|||||||
uuidParam := c.Param("uuid")
|
uuidParam := c.Param("uuid")
|
||||||
if uuidParam != "" {
|
if uuidParam != "" {
|
||||||
if !caller.IsAdmin && (caller.UUID != uuidParam) {
|
if !caller.IsAdmin && (caller.UUID != uuidParam) {
|
||||||
return NewUserError(http.StatusForbidden, "You are not authorized to update that user.")
|
return NewUserErrorWithCode(http.StatusForbidden, "You are not authorized to update that user.")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := uuid.Parse(uuidParam)
|
_, err := uuid.Parse(uuidParam)
|
||||||
@ -586,7 +586,7 @@ func (app *App) APIDeleteUser() func(c echo.Context) error {
|
|||||||
uuidParam := c.Param("uuid")
|
uuidParam := c.Param("uuid")
|
||||||
if uuidParam != "" {
|
if uuidParam != "" {
|
||||||
if !caller.IsAdmin && (caller.UUID != uuidParam) {
|
if !caller.IsAdmin && (caller.UUID != uuidParam) {
|
||||||
return NewUserError(http.StatusForbidden, "You are not authorized to update that user.")
|
return NewUserErrorWithCode(http.StatusForbidden, "You are not authorized to update that user.")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := uuid.Parse(uuidParam)
|
_, err := uuid.Parse(uuidParam)
|
||||||
@ -1075,7 +1075,7 @@ func (app *App) APIDeleteInvite() func(c echo.Context) error {
|
|||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
if result.RowsAffected == 0 {
|
if result.RowsAffected == 0 {
|
||||||
return NewUserError(http.StatusNotFound, "Unknown invite code")
|
return NewUserErrorWithCode(http.StatusNotFound, "Unknown invite code")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.NoContent(http.StatusNoContent)
|
return c.NoContent(http.StatusNoContent)
|
||||||
|
23
common.go
23
common.go
@ -82,7 +82,7 @@ type UserError struct {
|
|||||||
Code mo.Option[int]
|
Code mo.Option[int]
|
||||||
Message string
|
Message string
|
||||||
Plural mo.Option[Plural]
|
Plural mo.Option[Plural]
|
||||||
Params []interface{}
|
Params []any
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *UserError) Error() string {
|
func (e *UserError) Error() string {
|
||||||
@ -93,7 +93,7 @@ func (e *UserError) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *UserError) TranslatedError(l *gotext.Locale) string {
|
func (e *UserError) TranslatedError(l *gotext.Locale) string {
|
||||||
translatedParams := make([]interface{}, 0, len(e.Params))
|
translatedParams := make([]any, 0, len(e.Params))
|
||||||
for _, param := range e.Params {
|
for _, param := range e.Params {
|
||||||
switch v := param.(type) {
|
switch v := param.(type) {
|
||||||
case *UserError:
|
case *UserError:
|
||||||
@ -110,7 +110,14 @@ func (e *UserError) TranslatedError(l *gotext.Locale) string {
|
|||||||
return l.Get(e.Message, translatedParams...)
|
return l.Get(e.Message, translatedParams...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserError(code int, message string, params ...interface{}) error {
|
func NewUserError(message string, params ...any) error {
|
||||||
|
return &UserError{
|
||||||
|
Message: message,
|
||||||
|
Params: params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserErrorWithCode(code int, message string, params ...any) error {
|
||||||
return &UserError{
|
return &UserError{
|
||||||
Code: mo.Some(code),
|
Code: mo.Some(code),
|
||||||
Message: message,
|
Message: message,
|
||||||
@ -118,7 +125,7 @@ func NewUserError(code int, message string, params ...interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBadRequestUserError(message string, params ...interface{}) error {
|
func NewBadRequestUserError(message string, params ...any) error {
|
||||||
return &UserError{
|
return &UserError{
|
||||||
Code: mo.Some(http.StatusBadRequest),
|
Code: mo.Some(http.StatusBadRequest),
|
||||||
Message: message,
|
Message: message,
|
||||||
@ -324,10 +331,10 @@ func (app *App) GetSkinReader(reader io.Reader) (io.Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if app.Config.SkinSizeLimit > 0 && config.Width > app.Config.SkinSizeLimit {
|
if app.Config.SkinSizeLimit > 0 && config.Width > app.Config.SkinSizeLimit {
|
||||||
return nil, fmt.Errorf("skin must not be greater than %d pixels wide", app.Config.SkinSizeLimit)
|
return nil, NewUserError("skin must not be greater than %d pixels wide", app.Config.SkinSizeLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
mustBeMultipleError := fmt.Errorf("skin size must be a multiple of %d pixels wide by %d or %d pixels high", BASE_SKIN_WIDTH, BASE_SKIN_HEIGHT, BASE_SKIN_HEIGHT_LEGACY)
|
mustBeMultipleError := NewUserError("skin size must be a multiple of %d pixels wide by %d or %d pixels high", BASE_SKIN_WIDTH, BASE_SKIN_HEIGHT, BASE_SKIN_HEIGHT_LEGACY)
|
||||||
if config.Width%BASE_SKIN_WIDTH != 0 {
|
if config.Width%BASE_SKIN_WIDTH != 0 {
|
||||||
return nil, mustBeMultipleError
|
return nil, mustBeMultipleError
|
||||||
}
|
}
|
||||||
@ -351,10 +358,10 @@ func (app *App) GetCapeReader(reader io.Reader) (io.Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if app.Config.SkinSizeLimit > 0 && config.Width > app.Config.SkinSizeLimit {
|
if app.Config.SkinSizeLimit > 0 && config.Width > app.Config.SkinSizeLimit {
|
||||||
return nil, fmt.Errorf("cape must not be greater than %d pixels wide", app.Config.SkinSizeLimit)
|
return nil, NewUserError("cape must not be greater than %d pixels wide", app.Config.SkinSizeLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
mustBeMultipleError := fmt.Errorf("cape size must be a multiple of %d pixels wide by %d pixels high", BASE_CAPE_WIDTH, BASE_CAPE_HEIGHT)
|
mustBeMultipleError := NewUserError("cape size must be a multiple of %d pixels wide by %d pixels high", BASE_CAPE_WIDTH, BASE_CAPE_HEIGHT)
|
||||||
if config.Width%BASE_CAPE_WIDTH != 0 {
|
if config.Width%BASE_CAPE_WIDTH != 0 {
|
||||||
return nil, mustBeMultipleError
|
return nil, mustBeMultipleError
|
||||||
}
|
}
|
||||||
|
14
front.go
14
front.go
@ -102,7 +102,7 @@ func (app *App) GetLanguageMiddleware() func(echo.HandlerFunc) echo.HandlerFunc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
func (t *Template) Render(w io.Writer, name string, data any, c echo.Context) error {
|
||||||
return t.Templates[name].ExecuteTemplate(w, "base", data)
|
return t.Templates[name].ExecuteTemplate(w, "base", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,14 +155,14 @@ func (e *WebError) TranslatedError(l *gotext.Locale) string {
|
|||||||
return e.Err.TranslatedError(l)
|
return e.Err.TranslatedError(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWebError(returnURL string, message string, args ...interface{}) error {
|
func NewWebError(returnURL string, message string, args ...any) error {
|
||||||
return &WebError{
|
return &WebError{
|
||||||
Err: &UserError{Message: message, Params: args},
|
Err: &UserError{Message: message, Params: args},
|
||||||
ReturnURL: returnURL,
|
ReturnURL: returnURL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RenderHTML(templateString string, args ...interface{}) (template.HTML, error) {
|
func RenderHTML(templateString string, args ...any) (template.HTML, error) {
|
||||||
// If there are no args, skip parsing and return the "template" as-is
|
// If there are no args, skip parsing and return the "template" as-is
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return template.HTML(templateString), nil
|
return template.HTML(templateString), nil
|
||||||
@ -185,8 +185,8 @@ func RenderHTML(templateString string, args ...interface{}) (template.HTML, erro
|
|||||||
type baseContext struct {
|
type baseContext struct {
|
||||||
App *App
|
App *App
|
||||||
L *gotext.Locale
|
L *gotext.Locale
|
||||||
T func(string, ...interface{}) string
|
T func(string, ...any) string
|
||||||
TN func(string, string, int, ...interface{}) string
|
TN func(string, string, int, ...any) string
|
||||||
URL string
|
URL string
|
||||||
SuccessMessage string
|
SuccessMessage string
|
||||||
WarningMessage string
|
WarningMessage string
|
||||||
@ -540,12 +540,12 @@ func (app *App) getPreferredPlayerName(userInfo *oidc.UserInfo) mo.Option[string
|
|||||||
func (app *App) getIDTokenCookie(c *echo.Context) (*OIDCProvider, string, oidc.IDTokenClaims, error) {
|
func (app *App) getIDTokenCookie(c *echo.Context) (*OIDCProvider, string, oidc.IDTokenClaims, error) {
|
||||||
cookie, err := (*c).Cookie(ID_TOKEN_COOKIE_NAME)
|
cookie, err := (*c).Cookie(ID_TOKEN_COOKIE_NAME)
|
||||||
if err != nil || cookie.Value == "" {
|
if err != nil || cookie.Value == "" {
|
||||||
return nil, "", oidc.IDTokenClaims{}, &UserError{Message: "Missing ID token cookie"}
|
return nil, "", oidc.IDTokenClaims{}, NewUserError("Missing ID token cookie")
|
||||||
}
|
}
|
||||||
|
|
||||||
idTokenBytes, err := app.DecryptCookieValue(cookie.Value)
|
idTokenBytes, err := app.DecryptCookieValue(cookie.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", oidc.IDTokenClaims{}, &UserError{Message: "Invalid ID token"}
|
return nil, "", oidc.IDTokenClaims{}, NewUserError("Invalid ID token")
|
||||||
}
|
}
|
||||||
idToken := string(idTokenBytes)
|
idToken := string(idTokenBytes)
|
||||||
|
|
||||||
|
6
main.go
6
main.go
@ -79,7 +79,7 @@ type App struct {
|
|||||||
LocaleTags []language.Tag
|
LocaleTags []language.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogInfo(args ...interface{}) {
|
func LogInfo(args ...any) {
|
||||||
if !DRASL_TEST() {
|
if !DRASL_TEST() {
|
||||||
log.Println(args...)
|
log.Println(args...)
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ func makeRateLimiter(app *App) echo.MiddlewareFunc {
|
|||||||
// TODO write an IdentifierExtractor per authlib-injector spec "Limits should be placed on users, not client IPs"
|
// TODO write an IdentifierExtractor per authlib-injector spec "Limits should be placed on users, not client IPs"
|
||||||
Store: middleware.NewRateLimiterMemoryStore(requestsPerSecond),
|
Store: middleware.NewRateLimiterMemoryStore(requestsPerSecond),
|
||||||
DenyHandler: func(c echo.Context, identifier string, err error) error {
|
DenyHandler: func(c echo.Context, identifier string, err error) error {
|
||||||
return NewUserError(http.StatusTooManyRequests, "Too many requests. Try again later.")
|
return NewUserErrorWithCode(http.StatusTooManyRequests, "Too many requests. Try again later.")
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -615,7 +615,7 @@ func setup(config *Config) *App {
|
|||||||
// Post-setup
|
// Post-setup
|
||||||
|
|
||||||
// Make sure all DefaultAdmins are admins
|
// Make sure all DefaultAdmins are admins
|
||||||
err = app.DB.Table("users").Where("username in (?)", config.DefaultAdmins).Updates(map[string]interface{}{"is_admin": true}).Error
|
err = app.DB.Table("users").Where("username in (?)", config.DefaultAdmins).Updates(map[string]any{"is_admin": true}).Error
|
||||||
Check(err)
|
Check(err)
|
||||||
|
|
||||||
// Print an initial invite link if necessary
|
// Print an initial invite link if necessary
|
||||||
|
26
model.go
26
model.go
@ -72,14 +72,14 @@ func IsValidSkinModel(model string) bool {
|
|||||||
|
|
||||||
func UUIDToID(uuid string) (string, error) {
|
func UUIDToID(uuid string) (string, error) {
|
||||||
if len(uuid) != 36 {
|
if len(uuid) != 36 {
|
||||||
return "", &UserError{Message: "invalid UUID"}
|
return "", NewUserError("invalid UUID")
|
||||||
}
|
}
|
||||||
return strings.ReplaceAll(uuid, "-", ""), nil
|
return strings.ReplaceAll(uuid, "-", ""), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IDToUUID(id string) (string, error) {
|
func IDToUUID(id string) (string, error) {
|
||||||
if len(id) != 32 {
|
if len(id) != 32 {
|
||||||
return "", &UserError{Message: "invalid ID"}
|
return "", NewUserError("invalid ID")
|
||||||
}
|
}
|
||||||
return id[0:8] + "-" + id[8:12] + "-" + id[12:16] + "-" + id[16:20] + "-" + id[20:], nil
|
return id[0:8] + "-" + id[8:12] + "-" + id[12:16] + "-" + id[16:20] + "-" + id[20:], nil
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ func ParseUUID(idOrUUID string) (string, error) {
|
|||||||
}
|
}
|
||||||
return idOrUUID, nil
|
return idOrUUID, nil
|
||||||
}
|
}
|
||||||
return "", &UserError{Message: "invalid ID or UUID"}
|
return "", NewUserError("invalid ID or UUID")
|
||||||
}
|
}
|
||||||
|
|
||||||
type Plural struct {
|
type Plural struct {
|
||||||
@ -111,11 +111,11 @@ type Plural struct {
|
|||||||
|
|
||||||
func (app *App) ValidatePlayerName(playerName string) error {
|
func (app *App) ValidatePlayerName(playerName string) error {
|
||||||
if app.TransientLoginEligible(playerName) {
|
if app.TransientLoginEligible(playerName) {
|
||||||
return &UserError{Message: "name is reserved for transient login"}
|
return NewUserError("name is reserved for transient login")
|
||||||
}
|
}
|
||||||
maxLength := Constants.MaxPlayerNameLength
|
maxLength := Constants.MaxPlayerNameLength
|
||||||
if playerName == "" {
|
if playerName == "" {
|
||||||
return &UserError{Message: "can't be blank"}
|
return NewUserError("can't be blank")
|
||||||
}
|
}
|
||||||
if len(playerName) > maxLength {
|
if len(playerName) > maxLength {
|
||||||
return &UserError{
|
return &UserError{
|
||||||
@ -124,12 +124,12 @@ func (app *App) ValidatePlayerName(playerName string) error {
|
|||||||
Message: "can't be longer than %d characters",
|
Message: "can't be longer than %d characters",
|
||||||
N: maxLength,
|
N: maxLength,
|
||||||
}),
|
}),
|
||||||
Params: []interface{}{maxLength},
|
Params: []any{maxLength},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !app.ValidPlayerNameRegex.MatchString(playerName) {
|
if !app.ValidPlayerNameRegex.MatchString(playerName) {
|
||||||
return &UserError{Message: "must match the following regular expression: %s", Params: []interface{}{app.Config.ValidPlayerNameRegex}}
|
return NewUserError("must match the following regular expression: %s", app.Config.ValidPlayerNameRegex)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ func (app *App) ValidateUsername(username string) error {
|
|||||||
if emailErr == nil {
|
if emailErr == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &UserError{Message: "neither a valid player name (%s) nor an email address", Params: []interface{}{playerNameErr}}
|
return NewUserError("neither a valid player name (%s) nor an email address", playerNameErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) ValidatePlayerNameOrUUID(player string) error {
|
func (app *App) ValidatePlayerNameOrUUID(player string) error {
|
||||||
@ -152,7 +152,7 @@ func (app *App) ValidatePlayerNameOrUUID(player string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
_, uuidErr := uuid.Parse(player)
|
_, uuidErr := uuid.Parse(player)
|
||||||
if uuidErr != nil {
|
if uuidErr != nil {
|
||||||
return &UserError{Message: "not a valid player name or UUID"}
|
return NewUserError("not a valid player name or UUID")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ func (app *App) ValidatePlayerNameOrUUID(player string) error {
|
|||||||
|
|
||||||
func (app *App) ValidateMaxPlayerCount(maxPlayerCount int) error {
|
func (app *App) ValidateMaxPlayerCount(maxPlayerCount int) error {
|
||||||
if maxPlayerCount < 0 && maxPlayerCount != app.Constants.MaxPlayerCountUnlimited && maxPlayerCount != app.Constants.MaxPlayerCountUseDefault {
|
if maxPlayerCount < 0 && maxPlayerCount != app.Constants.MaxPlayerCountUnlimited && maxPlayerCount != app.Constants.MaxPlayerCountUseDefault {
|
||||||
return &UserError{Message: "must be greater than 0, or use -1 to indicate unlimited players, or use -2 to use the system default"}
|
return NewUserError("must be greater than 0, or use -1 to indicate unlimited players, or use -2 to use the system default")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ func (app *App) TransientLoginEligible(playerName string) bool {
|
|||||||
|
|
||||||
func (app *App) ValidatePassword(password string) error {
|
func (app *App) ValidatePassword(password string) error {
|
||||||
if password == "" {
|
if password == "" {
|
||||||
return &UserError{Message: "can't be blank"}
|
return NewUserError("can't be blank")
|
||||||
}
|
}
|
||||||
if len(password) < app.Config.MinPasswordLength {
|
if len(password) < app.Config.MinPasswordLength {
|
||||||
return &UserError{
|
return &UserError{
|
||||||
@ -218,7 +218,7 @@ func (app *App) ValidatePassword(password string) error {
|
|||||||
Message: "must be longer than %d characters",
|
Message: "must be longer than %d characters",
|
||||||
N: app.Config.MinPasswordLength,
|
N: app.Config.MinPasswordLength,
|
||||||
}),
|
}),
|
||||||
Params: []interface{}{app.Config.MinPasswordLength},
|
Params: []any{app.Config.MinPasswordLength},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -387,7 +387,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (app *App) GetClient(accessToken string, stalePolicy StaleTokenPolicy) *Client {
|
func (app *App) GetClient(accessToken string, stalePolicy StaleTokenPolicy) *Client {
|
||||||
token, err := jwt.ParseWithClaims(accessToken, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.ParseWithClaims(accessToken, &TokenClaims{}, func(token *jwt.Token) (any, error) {
|
||||||
return app.PrivateKey.Public(), nil
|
return app.PrivateKey.Public(), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
20
player.go
20
player.go
@ -115,7 +115,7 @@ func (app *App) CreatePlayer(
|
|||||||
Plural: mo.Some(Plural{
|
Plural: mo.Some(Plural{
|
||||||
Message: "You are only allowed to own %d players", N: maxPlayerCount,
|
Message: "You are only allowed to own %d players", N: maxPlayerCount,
|
||||||
}),
|
}),
|
||||||
Params: []interface{}{maxPlayerCount},
|
Params: []any{maxPlayerCount},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ func (app *App) ValidateChallenge(playerName string, challengeToken *string) (*P
|
|||||||
|
|
||||||
if res.StatusCode != http.StatusOK {
|
if res.StatusCode != http.StatusOK {
|
||||||
log.Printf("Request to registration server at %s resulted in status code %d\n", base.String(), res.StatusCode)
|
log.Printf("Request to registration server at %s resulted in status code %d\n", base.String(), res.StatusCode)
|
||||||
return nil, &UserError{Message: "registration server returned an error"}
|
return nil, NewUserError("registration server returned an error")
|
||||||
}
|
}
|
||||||
|
|
||||||
var idRes PlayerNameToIDResponse
|
var idRes PlayerNameToIDResponse
|
||||||
@ -429,7 +429,7 @@ func (app *App) ValidateChallenge(playerName string, challengeToken *string) (*P
|
|||||||
|
|
||||||
if res.StatusCode != http.StatusOK {
|
if res.StatusCode != http.StatusOK {
|
||||||
log.Printf("Request to registration server at %s resulted in status code %d\n", base.String(), res.StatusCode)
|
log.Printf("Request to registration server at %s resulted in status code %d\n", base.String(), res.StatusCode)
|
||||||
return nil, &UserError{Message: "registration server returned an error"}
|
return nil, NewUserError("registration server returned an error")
|
||||||
}
|
}
|
||||||
|
|
||||||
var profileRes SessionProfileResponse
|
var profileRes SessionProfileResponse
|
||||||
@ -465,7 +465,7 @@ func (app *App) ValidateChallenge(playerName string, challengeToken *string) (*P
|
|||||||
}
|
}
|
||||||
|
|
||||||
if texture.Textures.Skin == nil {
|
if texture.Textures.Skin == nil {
|
||||||
return nil, &UserError{Message: "player does not have a skin"}
|
return nil, NewUserError("player does not have a skin")
|
||||||
}
|
}
|
||||||
res, err = MakeHTTPClient().Get(texture.Textures.Skin.URL)
|
res, err = MakeHTTPClient().Get(texture.Textures.Skin.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -479,7 +479,7 @@ func (app *App) ValidateChallenge(playerName string, challengeToken *string) (*P
|
|||||||
}
|
}
|
||||||
img, ok := rgba_img.(*image.NRGBA)
|
img, ok := rgba_img.(*image.NRGBA)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &UserError{Message: "invalid image"}
|
return nil, NewUserError("invalid image")
|
||||||
}
|
}
|
||||||
|
|
||||||
challenge := make([]byte, 64)
|
challenge := make([]byte, 64)
|
||||||
@ -497,19 +497,19 @@ func (app *App) ValidateChallenge(playerName string, challengeToken *string) (*P
|
|||||||
}
|
}
|
||||||
|
|
||||||
if challengeToken == nil {
|
if challengeToken == nil {
|
||||||
return nil, &UserError{Message: "missing challenge token"}
|
return nil, NewUserError("missing challenge token")
|
||||||
}
|
}
|
||||||
correctChallenge := app.GetChallenge(playerName, *challengeToken)
|
correctChallenge := app.GetChallenge(playerName, *challengeToken)
|
||||||
|
|
||||||
if !bytes.Equal(challenge, correctChallenge) {
|
if !bytes.Equal(challenge, correctChallenge) {
|
||||||
return nil, &UserError{Message: "skin does not match"}
|
return nil, NewUserError("skin does not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &details, nil
|
return &details, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &UserError{Message: "registration server didn't return textures"}
|
return nil, NewUserError("registration server didn't return textures")
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeChallengeToken() (string, error) {
|
func MakeChallengeToken() (string, error) {
|
||||||
@ -591,11 +591,11 @@ func (app *App) InvalidateUser(db *gorm.DB, user *User) error {
|
|||||||
|
|
||||||
func (app *App) DeletePlayer(caller *User, player *Player) error {
|
func (app *App) DeletePlayer(caller *User, player *Player) error {
|
||||||
if !app.Config.AllowAddingDeletingPlayers && !caller.IsAdmin {
|
if !app.Config.AllowAddingDeletingPlayers && !caller.IsAdmin {
|
||||||
return NewUserError(http.StatusForbidden, "You are not allowed to delete players.")
|
return NewUserErrorWithCode(http.StatusForbidden, "You are not allowed to delete players.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if caller.UUID != player.UserUUID && !caller.IsAdmin {
|
if caller.UUID != player.UserUUID && !caller.IsAdmin {
|
||||||
return NewUserError(http.StatusForbidden, "You don't own that player.")
|
return NewUserErrorWithCode(http.StatusForbidden, "You don't own that player.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.DB.Delete(player).Error; err != nil {
|
if err := app.DB.Delete(player).Error; err != nil {
|
||||||
|
@ -223,7 +223,7 @@ func (ts *TestSuite) Get(t *testing.T, server *echo.Echo, path string, cookies [
|
|||||||
return rec
|
return rec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TestSuite) Delete(t *testing.T, server *echo.Echo, path string, payload interface{}, cookies []http.Cookie, accessToken *string) *httptest.ResponseRecorder {
|
func (ts *TestSuite) Delete(t *testing.T, server *echo.Echo, path string, payload any, cookies []http.Cookie, accessToken *string) *httptest.ResponseRecorder {
|
||||||
body, err := json.Marshal(payload)
|
body, err := json.Marshal(payload)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req := httptest.NewRequest(http.MethodDelete, path, bytes.NewBuffer(body))
|
req := httptest.NewRequest(http.MethodDelete, path, bytes.NewBuffer(body))
|
||||||
@ -288,7 +288,7 @@ func (ts *TestSuite) PutMultipart(t *testing.T, server *echo.Echo, path string,
|
|||||||
return rec
|
return rec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TestSuite) PostJSON(t *testing.T, server *echo.Echo, path string, payload interface{}, cookies []http.Cookie, accessToken *string) *httptest.ResponseRecorder {
|
func (ts *TestSuite) PostJSON(t *testing.T, server *echo.Echo, path string, payload any, cookies []http.Cookie, accessToken *string) *httptest.ResponseRecorder {
|
||||||
body, err := json.Marshal(payload)
|
body, err := json.Marshal(payload)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req := httptest.NewRequest(http.MethodPost, path, bytes.NewBuffer(body))
|
req := httptest.NewRequest(http.MethodPost, path, bytes.NewBuffer(body))
|
||||||
@ -305,7 +305,7 @@ func (ts *TestSuite) PostJSON(t *testing.T, server *echo.Echo, path string, payl
|
|||||||
return rec
|
return rec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TestSuite) PatchJSON(t *testing.T, server *echo.Echo, path string, payload interface{}, cookies []http.Cookie, accessToken *string) *httptest.ResponseRecorder {
|
func (ts *TestSuite) PatchJSON(t *testing.T, server *echo.Echo, path string, payload any, cookies []http.Cookie, accessToken *string) *httptest.ResponseRecorder {
|
||||||
body, err := json.Marshal(payload)
|
body, err := json.Marshal(payload)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(body))
|
req := httptest.NewRequest(http.MethodPatch, path, bytes.NewBuffer(body))
|
||||||
|
16
user.go
16
user.go
@ -356,14 +356,14 @@ func (app *App) CreateUser(
|
|||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var PasswordLoginNotAllowedError error = NewUserError(http.StatusUnauthorized, "Password login is not allowed.")
|
var PasswordLoginNotAllowedError error = NewUserErrorWithCode(http.StatusUnauthorized, "Password login is not allowed.")
|
||||||
|
|
||||||
func (app *App) AuthenticateUserForMigration(username string, password string) (User, error) {
|
func (app *App) AuthenticateUserForMigration(username string, password string) (User, error) {
|
||||||
var user User
|
var user User
|
||||||
result := app.DB.First(&user, "username = ?", username)
|
result := app.DB.First(&user, "username = ?", username)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
return User{}, NewUserError(http.StatusUnauthorized, "User not found.")
|
return User{}, NewUserErrorWithCode(http.StatusUnauthorized, "User not found.")
|
||||||
}
|
}
|
||||||
return User{}, result.Error
|
return User{}, result.Error
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ func (app *App) AuthenticateUserForMigration(username string, password string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(passwordHash, user.PasswordHash) {
|
if !bytes.Equal(passwordHash, user.PasswordHash) {
|
||||||
return User{}, NewUserError(http.StatusUnauthorized, "Incorrect password.")
|
return User{}, NewUserErrorWithCode(http.StatusUnauthorized, "Incorrect password.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
@ -389,7 +389,7 @@ func (app *App) AuthenticateUser(username string, password string) (User, error)
|
|||||||
result := app.DB.First(&user, "username = ?", username)
|
result := app.DB.First(&user, "username = ?", username)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
return User{}, NewUserError(http.StatusUnauthorized, "User not found.")
|
return User{}, NewUserErrorWithCode(http.StatusUnauthorized, "User not found.")
|
||||||
}
|
}
|
||||||
return User{}, result.Error
|
return User{}, result.Error
|
||||||
}
|
}
|
||||||
@ -404,11 +404,11 @@ func (app *App) AuthenticateUser(username string, password string) (User, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(passwordHash, user.PasswordHash) {
|
if !bytes.Equal(passwordHash, user.PasswordHash) {
|
||||||
return User{}, NewUserError(http.StatusUnauthorized, "Incorrect password.")
|
return User{}, NewUserErrorWithCode(http.StatusUnauthorized, "Incorrect password.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsLocked {
|
if user.IsLocked {
|
||||||
return User{}, NewUserError(http.StatusForbidden, "User is locked.")
|
return User{}, NewUserErrorWithCode(http.StatusForbidden, "User is locked.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
@ -538,7 +538,7 @@ func (app *App) SetIsLocked(db *gorm.DB, user *User, isLocked bool) error {
|
|||||||
|
|
||||||
func (app *App) DeleteUser(caller *User, user *User) error {
|
func (app *App) DeleteUser(caller *User, user *User) error {
|
||||||
if !caller.IsAdmin && caller.UUID != user.UUID {
|
if !caller.IsAdmin && caller.UUID != user.UUID {
|
||||||
return NewUserError(http.StatusForbidden, "You are not an admin.")
|
return NewUserErrorWithCode(http.StatusForbidden, "You are not an admin.")
|
||||||
}
|
}
|
||||||
|
|
||||||
oldSkinHashes := make([]*string, 0, len(user.Players))
|
oldSkinHashes := make([]*string, 0, len(user.Players))
|
||||||
@ -661,7 +661,7 @@ func (app *App) DeleteOIDCIdentity(
|
|||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
if result.RowsAffected == 0 {
|
if result.RowsAffected == 0 {
|
||||||
return NewUserError(http.StatusNotFound, "No linked %s account found.", providerName)
|
return NewUserErrorWithCode(http.StatusNotFound, "No linked %s account found.", providerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
var count int64
|
var count int64
|
||||||
|
Loading…
x
Reference in New Issue
Block a user