mirror of
https://github.com/unmojang/drasl.git
synced 2025-08-04 03:16:05 -04:00
Allow setting max player count on edit user page
This commit is contained in:
parent
1da3ac2601
commit
d6d29b2274
7
api.go
7
api.go
@ -305,6 +305,7 @@ type APICreateUserRequest struct {
|
|||||||
SkinURL *string `json:"skinUrl" example:"https://example.com/skin.png"` // Optional. URL to skin file. Do not specify both `skinBase64` and `skinUrl`.
|
SkinURL *string `json:"skinUrl" example:"https://example.com/skin.png"` // Optional. URL to skin file. Do not specify both `skinBase64` and `skinUrl`.
|
||||||
CapeBase64 *string `json:"capeBase64" example:"iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAABcGlDQ1BpY2MAACiRdZG9S8NAGMaf"` // Optional. Base64-encoded cape PNG. Example value truncated for brevity. Do not specify both `capeBase64` and `capeUrl`.
|
CapeBase64 *string `json:"capeBase64" example:"iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAABcGlDQ1BpY2MAACiRdZG9S8NAGMaf"` // Optional. Base64-encoded cape PNG. Example value truncated for brevity. Do not specify both `capeBase64` and `capeUrl`.
|
||||||
CapeURL *string `json:"capeUrl" example:"https://example.com/cape.png"` // Optional. URL to cape file. Do not specify both `capeBase64` and `capeUrl`.
|
CapeURL *string `json:"capeUrl" example:"https://example.com/cape.png"` // Optional. URL to cape file. Do not specify both `capeBase64` and `capeUrl`.
|
||||||
|
MaxPlayerCount *int `json:"maxPlayerCount" example:"3"` // Optional. Maximum number of players a user is allowed to create. -1 means unlimited players. -2 means use the default configured value.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a user (admin only)
|
// Create a user (admin only)
|
||||||
@ -354,6 +355,7 @@ func (app *App) APICreateUser() func(c echo.Context) error {
|
|||||||
req.ExistingPlayer,
|
req.ExistingPlayer,
|
||||||
nil, // challengeToken
|
nil, // challengeToken
|
||||||
req.FallbackPlayer,
|
req.FallbackPlayer,
|
||||||
|
req.MaxPlayerCount,
|
||||||
req.SkinModel,
|
req.SkinModel,
|
||||||
skinReader,
|
skinReader,
|
||||||
req.SkinURL,
|
req.SkinURL,
|
||||||
@ -379,6 +381,7 @@ type APIUpdateUserRequest struct {
|
|||||||
IsLocked *bool `json:"isLocked" example:"false"` // Optional. Pass `true` to lock (disable), `false` to unlock user.
|
IsLocked *bool `json:"isLocked" example:"false"` // Optional. Pass `true` to lock (disable), `false` to unlock user.
|
||||||
ResetAPIToken bool `json:"resetApiToken" example:"true"` // Pass `true` to reset the user's API token
|
ResetAPIToken bool `json:"resetApiToken" example:"true"` // Pass `true` to reset the user's API token
|
||||||
PreferredLanguage *string `json:"preferredLanguage" example:"en"` // Optional. One of the two-letter codes in https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html. Used by Minecraft.
|
PreferredLanguage *string `json:"preferredLanguage" example:"en"` // Optional. One of the two-letter codes in https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html. Used by Minecraft.
|
||||||
|
MaxPlayerCount *int `json:"maxPlayerCount" example:"3"` // Optional. Maximum number of players a user is allowed to create. -1 means unlimited players. -2 means use the default configured value.
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIUpdateUser godoc
|
// APIUpdateUser godoc
|
||||||
@ -426,7 +429,7 @@ func (app *App) APIUpdateUser() func(c echo.Context) error {
|
|||||||
req.IsLocked,
|
req.IsLocked,
|
||||||
req.ResetAPIToken,
|
req.ResetAPIToken,
|
||||||
req.PreferredLanguage,
|
req.PreferredLanguage,
|
||||||
nil,
|
req.MaxPlayerCount,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -470,7 +473,7 @@ func (app *App) APIUpdateSelf() func(c echo.Context) error {
|
|||||||
req.IsLocked,
|
req.IsLocked,
|
||||||
req.ResetAPIToken,
|
req.ResetAPIToken,
|
||||||
req.PreferredLanguage,
|
req.PreferredLanguage,
|
||||||
nil,
|
req.MaxPlayerCount,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
16
front.go
16
front.go
@ -612,7 +612,7 @@ func FrontUpdateUser(app *App) func(c echo.Context) error {
|
|||||||
password := nilIfEmpty(c.FormValue("password"))
|
password := nilIfEmpty(c.FormValue("password"))
|
||||||
resetAPIToken := c.FormValue("resetApiToken") == "on"
|
resetAPIToken := c.FormValue("resetApiToken") == "on"
|
||||||
preferredLanguage := nilIfEmpty(c.FormValue("preferredLanguage"))
|
preferredLanguage := nilIfEmpty(c.FormValue("preferredLanguage"))
|
||||||
// maxPlayerCount := c.FormValue("maxPlayerCount")
|
maxPlayerCountString := c.FormValue("maxPlayerCount")
|
||||||
|
|
||||||
var targetUser *User
|
var targetUser *User
|
||||||
if targetUUID == nil || *targetUUID == user.UUID {
|
if targetUUID == nil || *targetUUID == user.UUID {
|
||||||
@ -629,6 +629,17 @@ func FrontUpdateUser(app *App) func(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxPlayerCount := targetUser.MaxPlayerCount
|
||||||
|
if maxPlayerCountString == "" {
|
||||||
|
maxPlayerCount = app.Constants.MaxPlayerCountUseDefault
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
maxPlayerCount, err = strconv.Atoi(maxPlayerCountString)
|
||||||
|
if err != nil {
|
||||||
|
return NewWebError(returnURL, "Max player count must be an integer.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_, err := app.UpdateUser(
|
_, err := app.UpdateUser(
|
||||||
app.DB,
|
app.DB,
|
||||||
user, // caller
|
user, // caller
|
||||||
@ -638,7 +649,7 @@ func FrontUpdateUser(app *App) func(c echo.Context) error {
|
|||||||
nil, // isLocked
|
nil, // isLocked
|
||||||
resetAPIToken,
|
resetAPIToken,
|
||||||
preferredLanguage,
|
preferredLanguage,
|
||||||
nil,
|
&maxPlayerCount,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var userError *UserError
|
var userError *UserError
|
||||||
@ -926,6 +937,7 @@ func FrontRegister(app *App) func(c echo.Context) error {
|
|||||||
existingPlayer,
|
existingPlayer,
|
||||||
challengeToken,
|
challengeToken,
|
||||||
nil, // fallbackPlayer
|
nil, // fallbackPlayer
|
||||||
|
nil, // maxPlayerCount
|
||||||
nil, // skinModel
|
nil, // skinModel
|
||||||
nil, // skinReader
|
nil, // skinReader
|
||||||
nil, // skinURL
|
nil, // skinURL
|
||||||
|
@ -924,6 +924,7 @@ func (ts *TestSuite) testUserUpdate(t *testing.T) {
|
|||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
writer := multipart.NewWriter(body)
|
writer := multipart.NewWriter(body)
|
||||||
assert.Nil(t, writer.WriteField("uuid", takenUser.UUID))
|
assert.Nil(t, writer.WriteField("uuid", takenUser.UUID))
|
||||||
|
assert.Nil(t, writer.WriteField("maxPlayerCount", "3"))
|
||||||
assert.Nil(t, writer.WriteField("preferredLanguage", "es"))
|
assert.Nil(t, writer.WriteField("preferredLanguage", "es"))
|
||||||
assert.Nil(t, writer.WriteField("returnUrl", ts.App.FrontEndURL+"/web/user"))
|
assert.Nil(t, writer.WriteField("returnUrl", ts.App.FrontEndURL+"/web/user"))
|
||||||
assert.Nil(t, writer.Close())
|
assert.Nil(t, writer.Close())
|
||||||
@ -941,6 +942,17 @@ func (ts *TestSuite) testUserUpdate(t *testing.T) {
|
|||||||
rec := ts.PostMultipart(t, ts.Server, "/web/update-user", body, writer, []http.Cookie{*takenBrowserTokenCookie}, nil)
|
rec := ts.PostMultipart(t, ts.Server, "/web/update-user", body, writer, []http.Cookie{*takenBrowserTokenCookie}, nil)
|
||||||
ts.updateUserShouldFail(t, rec, "You are not an admin.", ts.App.FrontEndURL)
|
ts.updateUserShouldFail(t, rec, "You are not an admin.", ts.App.FrontEndURL)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// Non-admin should not be able to increase their max player count
|
||||||
|
body := &bytes.Buffer{}
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
assert.Nil(t, writer.WriteField("uuid", takenUser.UUID))
|
||||||
|
assert.Nil(t, writer.WriteField("maxPlayerCount", "-1"))
|
||||||
|
assert.Nil(t, writer.WriteField("returnUrl", ts.App.FrontEndURL+"/web/user"))
|
||||||
|
assert.Nil(t, writer.Close())
|
||||||
|
rec := ts.PostMultipart(t, ts.Server, "/web/update-user", body, writer, []http.Cookie{*takenBrowserTokenCookie}, nil)
|
||||||
|
ts.updateUserShouldFail(t, rec, "Cannot set a max player count without admin privileges.", ts.App.FrontEndURL+"/web/user")
|
||||||
|
}
|
||||||
{
|
{
|
||||||
// Invalid preferred language should fail
|
// Invalid preferred language should fail
|
||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
|
10
swagger.json
10
swagger.json
@ -677,6 +677,11 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"example": false
|
"example": false
|
||||||
},
|
},
|
||||||
|
"maxPlayerCount": {
|
||||||
|
"description": "Optional. Maximum number of players a user is allowed to create. -1 means unlimited players. -2 means use the default configured value.",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 3
|
||||||
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"description": "Plaintext password",
|
"description": "Plaintext password",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -848,6 +853,11 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"example": false
|
"example": false
|
||||||
},
|
},
|
||||||
|
"maxPlayerCount": {
|
||||||
|
"description": "Optional. Maximum number of players a user is allowed to create. -1 means unlimited players. -2 means use the default configured value.",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 3
|
||||||
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"description": "Optional. New plaintext password",
|
"description": "Optional. New plaintext password",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
18
user.go
18
user.go
@ -31,6 +31,7 @@ func (app *App) CreateUser(
|
|||||||
existingPlayer bool,
|
existingPlayer bool,
|
||||||
challengeToken *string,
|
challengeToken *string,
|
||||||
fallbackPlayer *string,
|
fallbackPlayer *string,
|
||||||
|
maxPlayerCount *int,
|
||||||
skinModel *string,
|
skinModel *string,
|
||||||
skinReader *io.Reader,
|
skinReader *io.Reader,
|
||||||
skinURL *string,
|
skinURL *string,
|
||||||
@ -159,6 +160,18 @@ func (app *App) CreateUser(
|
|||||||
return User{}, NewBadRequestUserError("Cannot make a new locked user without admin privileges.")
|
return User{}, NewBadRequestUserError("Cannot make a new locked user without admin privileges.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxPlayerCountInt := Constants.MaxPlayerCountUseDefault
|
||||||
|
if maxPlayerCount != nil {
|
||||||
|
if !callerIsAdmin {
|
||||||
|
return User{}, NewBadRequestUserError("Cannot set a max player count without admin privileges.")
|
||||||
|
}
|
||||||
|
err := app.ValidateMaxPlayerCount(*maxPlayerCount)
|
||||||
|
if err != nil {
|
||||||
|
return User{}, NewBadRequestUserError("Invalid max player count: %s", err)
|
||||||
|
}
|
||||||
|
maxPlayerCountInt = *maxPlayerCount
|
||||||
|
}
|
||||||
|
|
||||||
apiToken, err := MakeAPIToken()
|
apiToken, err := MakeAPIToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return User{}, err
|
return User{}, err
|
||||||
@ -172,8 +185,8 @@ func (app *App) CreateUser(
|
|||||||
PasswordSalt: passwordSalt,
|
PasswordSalt: passwordSalt,
|
||||||
PasswordHash: passwordHash,
|
PasswordHash: passwordHash,
|
||||||
PreferredLanguage: app.Config.DefaultPreferredLanguage,
|
PreferredLanguage: app.Config.DefaultPreferredLanguage,
|
||||||
|
MaxPlayerCount: maxPlayerCountInt,
|
||||||
APIToken: apiToken,
|
APIToken: apiToken,
|
||||||
MaxPlayerCount: Constants.MaxPlayerCountUseDefault,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player
|
// Player
|
||||||
@ -334,6 +347,9 @@ func (app *App) UpdateUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if maxPlayerCount != nil {
|
if maxPlayerCount != nil {
|
||||||
|
if !callerIsAdmin {
|
||||||
|
return User{}, NewBadRequestUserError("Cannot set a max player count without admin privileges.")
|
||||||
|
}
|
||||||
err := app.ValidateMaxPlayerCount(*maxPlayerCount)
|
err := app.ValidateMaxPlayerCount(*maxPlayerCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return User{}, NewBadRequestUserError("Invalid max player count: %s", err)
|
return User{}, NewBadRequestUserError("Invalid max player count: %s", err)
|
||||||
|
@ -153,6 +153,19 @@
|
|||||||
method="post"
|
method="post"
|
||||||
enctype="multipart/form-data"
|
enctype="multipart/form-data"
|
||||||
>
|
>
|
||||||
|
{{ if .User.IsAdmin }}
|
||||||
|
<p>
|
||||||
|
<label for="max-player-count">Max number of players. Specify -1 to allow unlimited players or leave blank to reset to the configured default value.</label><br />
|
||||||
|
<input
|
||||||
|
name="maxPlayerCount"
|
||||||
|
type="number"
|
||||||
|
{{ if .TargetUser.IsAdmin }}disabled{{ end }}
|
||||||
|
value="{{ if or .TargetUser.IsAdmin (eq .TargetUser.MaxPlayerCount $.App.Constants.MaxPlayerCountUnlimited) }}-1{{ else if eq .TargetUser.MaxPlayerCount $.App.Constants.MaxPlayerCountUseDefault}}{{ else }}{{ .TargetUser.MaxPlayerCount }}{{ end }}"
|
||||||
|
placeholder="{{ .App.Config.DefaultMaxPlayerCount }}"
|
||||||
|
min="-1">
|
||||||
|
</input>
|
||||||
|
</p>
|
||||||
|
{{ end }}
|
||||||
<p>
|
<p>
|
||||||
<label for="password">Password</label><br />
|
<label for="password">Password</label><br />
|
||||||
<input
|
<input
|
||||||
|
Loading…
x
Reference in New Issue
Block a user