mirror of
https://github.com/unmojang/drasl.git
synced 2025-08-03 02:46:03 -04:00
Add PlayerUUIDGeneration option
This commit is contained in:
parent
9f940f666c
commit
c3cb43885f
4
api.go
4
api.go
@ -384,7 +384,7 @@ type APICreateUserRequest struct {
|
||||
IsAdmin bool `json:"isAdmin" example:"true"` // Whether the user is an admin
|
||||
IsLocked bool `json:"isLocked" example:"false"` // Whether the user is locked (disabled)
|
||||
RequestAPIToken bool `json:"requestApiToken" example:"true"` // Whether to include an API token for the user in the response
|
||||
ChosenUUID *string `json:"chosenUuid" example:"557e0c92-2420-4704-8840-a790ea11551c"` // Optional. Specify a UUID for the player of the new user. If omitted, a random UUID will be generated.
|
||||
ChosenUUID *string `json:"chosenUuid" example:"557e0c92-2420-4704-8840-a790ea11551c"` // Optional. Specify a UUID for the player of the new user. If omitted, a UUID will be generated according to the `PlayerUUIDGeneration` configuration option.
|
||||
ExistingPlayer bool `json:"existingPlayer" example:"false"` // If true, the new user's player will get the UUID of the existing player with the specified PlayerName. See `RegistrationExistingPlayer` in configuration.md.
|
||||
InviteCode *string `json:"inviteCode" example:"rqjJwh0yMjO"` // Invite code to use. Optional even if the `RequireInvite` configuration option is set; admin API users can bypass `RequireInvite`.
|
||||
PlayerName *string `json:"playerName" example:"MyPlayerName"` // Optional. Player name. Can be different from the user's username. If omitted, the user's username will be used.
|
||||
@ -693,7 +693,7 @@ func (app *App) APIGetPlayers() func(c echo.Context) error {
|
||||
type APICreatePlayerRequest struct {
|
||||
Name string `json:"name" example:"MyPlayerName"` // Player name.
|
||||
UserUUID *string `json:"userUuid" example:"f9b9af62-da83-4ec7-aeea-de48c621822c"` // Optional. UUID of the owning user. If omitted, the player will be added to the calling user's account.
|
||||
ChosenUUID *string `json:"chosenUuid" example:"557e0c92-2420-4704-8840-a790ea11551c"` // Optional. Specify a UUID for the new player. If omitted, a random UUID will be generated.
|
||||
ChosenUUID *string `json:"chosenUuid" example:"557e0c92-2420-4704-8840-a790ea11551c"` // Optional. Specify a UUID for the new player. If omitted, a UUID will be generated according to the `PlayerUUIDGeneration` configuration option.
|
||||
ExistingPlayer bool `json:"existingPlayer" example:"false"` // If true, the new player will get the UUID of the existing player with the specified PlayerName. See `RegistrationExistingPlayer` in configuration.md.
|
||||
FallbackPlayer *string `json:"fallbackPlayer" example:"Notch"` // Can be a UUID or a player name. If you don't set a skin or cape, this player's skin on one of the fallback API servers will be used instead.
|
||||
ChallengeToken *string `json:"challengeToken" example:"iK1B2FzLc5fMP94VmUR3KC"` // Challenge token to use when verifying ownership of another player. Call /drasl/api/v2/challenge-skin first to get a skin and token. See `RequireSkinVerification` in configuration.md.
|
||||
|
@ -1263,7 +1263,7 @@
|
||||
"example": "iK1B2FzLc5fMP94VmUR3KC"
|
||||
},
|
||||
"chosenUuid": {
|
||||
"description": "Optional. Specify a UUID for the new player. If omitted, a random UUID will be generated.",
|
||||
"description": "Optional. Specify a UUID for the new player. If omitted, a UUID will be generated according to the `PlayerUUIDGeneration` configuration option.",
|
||||
"type": "string",
|
||||
"example": "557e0c92-2420-4704-8840-a790ea11551c"
|
||||
},
|
||||
@ -1318,7 +1318,7 @@
|
||||
"example": "https://example.com/cape.png"
|
||||
},
|
||||
"chosenUuid": {
|
||||
"description": "Optional. Specify a UUID for the player of the new user. If omitted, a random UUID will be generated.",
|
||||
"description": "Optional. Specify a UUID for the player of the new user. If omitted, a UUID will be generated according to the `PlayerUUIDGeneration` configuration option.",
|
||||
"type": "string",
|
||||
"example": "557e0c92-2420-4704-8840-a790ea11551c"
|
||||
},
|
||||
|
@ -959,3 +959,12 @@ func NewFallbackAPIServer(config *FallbackAPIServerConfig) (FallbackAPIServer, e
|
||||
PlayerNameToIDJobCh: make(chan []playerNameToIDJob),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (app *App) NewPlayerUUID(playerName string) (string, error) {
|
||||
switch app.Config.PlayerUUIDGeneration {
|
||||
case PlayerUUIDGenerationOffline:
|
||||
return OfflineUUID(playerName)
|
||||
default:
|
||||
return uuid.New().String(), nil
|
||||
}
|
||||
}
|
||||
|
22
config.go
22
config.go
@ -143,6 +143,7 @@ type BaseConfig struct {
|
||||
ListenAddress string
|
||||
LogRequests bool
|
||||
MinPasswordLength int
|
||||
PlayerUUIDGeneration string
|
||||
PreMigrationBackups bool
|
||||
RateLimit rateLimitConfig
|
||||
RegistrationExistingPlayer registrationExistingPlayerConfig
|
||||
@ -216,13 +217,14 @@ func DefaultRawConfig() RawConfig {
|
||||
ImportExistingPlayer: importExistingPlayerConfig{
|
||||
Allow: false,
|
||||
},
|
||||
InstanceName: "Drasl",
|
||||
ListenAddress: "0.0.0.0:25585",
|
||||
LogRequests: true,
|
||||
MinPasswordLength: 8,
|
||||
OfflineSkins: true,
|
||||
PreMigrationBackups: true,
|
||||
RateLimit: defaultRateLimitConfig,
|
||||
InstanceName: "Drasl",
|
||||
ListenAddress: "0.0.0.0:25585",
|
||||
LogRequests: true,
|
||||
MinPasswordLength: 8,
|
||||
OfflineSkins: true,
|
||||
PlayerUUIDGeneration: "random",
|
||||
PreMigrationBackups: true,
|
||||
RateLimit: defaultRateLimitConfig,
|
||||
RegistrationExistingPlayer: registrationExistingPlayerConfig{
|
||||
Allow: false,
|
||||
},
|
||||
@ -379,6 +381,12 @@ func CleanConfig(rawConfig *RawConfig) (Config, error) {
|
||||
return Config{}, errors.New("If RegisterNewPlayer is allowed, CreateNewPlayer must be allowed.")
|
||||
}
|
||||
}
|
||||
switch config.PlayerUUIDGeneration {
|
||||
case PlayerUUIDGenerationRandom:
|
||||
case PlayerUUIDGenerationOffline:
|
||||
default:
|
||||
return Config{}, errors.New(`PlayerUUIDGeneration must be either "random" or "offline".`)
|
||||
}
|
||||
if config.RegistrationExistingPlayer.Allow {
|
||||
if !config.ImportExistingPlayer.Allow {
|
||||
return Config{}, errors.New("If RegistrationExistingPlayer is allowed, ImportExistingPlayer must be allowed.")
|
||||
|
@ -63,9 +63,9 @@ Other available options:
|
||||
<!-- - `UsernameRegex`: If a username matches this regular expression, it will be allowed to log in with the shared password. Use `".*"` to allow transient login for any username. String. Example value: `"[Bot] .*"`. -->
|
||||
<!-- - `Password`: The shared password for transient login. Not restricted by `MinPasswordLength`. String. Example value: `"hunter2"`. -->
|
||||
|
||||
- `[CreateNewPlayer]`: Policy for creating new players, i.e. players with a random or user-specified UUID.
|
||||
- `[CreateNewPlayer]`: Policy for creating new players.
|
||||
- `Allow`: Allow users to create players with new UUIDs, up to their individual `MaxPlayerCount` limit. Boolean. Default value: `true`.
|
||||
- `AllowChoosingUUID`: Allow users to choose a UUID for the new player. If disabled, the new player's UUID will always be randomly chosen. Boolean. Default value: `false`.
|
||||
- `AllowChoosingUUID`: Allow users to choose a UUID for the new player. If disabled, the new player's UUID will always be generated according to the strategy specified by the `PlayerUUIDGeneration` option. Boolean. Default value: `false`.
|
||||
- `[RegistrationNewPlayer]`
|
||||
- `Allow`: Allow users to register a new Drasl account by creating a player with a new UUID. Requires `CreateNewPlayer.Allow = true`. Boolean. Default value: `true`.
|
||||
- `RequireInvite`: Whether registration requires an invite. If enabled, users will only be able to create a new account if they use an invite link generated by an admin (see `DefaultAdmins`). Boolean. Default value: `false`.
|
||||
@ -119,3 +119,4 @@ Other available options:
|
||||
- `AllowTextureFromURL`: Allow users to specify a skin or cape by providing a URL to the texture file. Previously, this option was always allowed; now it is opt-in. Admins can do this regardless of this setting. Boolean. Default value: `false`.
|
||||
- `ValidPlayerNameRegex`: Regular expression (regex) that player names must match. Currently, Drasl usernames are validated using this regex too. Player names will be limited to a maximum of 16 characters no matter what. Mojang allows the characters `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_`, and by default, Drasl follows suit. Minecraft servers may misbehave if additional characters are allowed. Change to `.+` if you want to allow any player name (that is 16 characters or shorter). String. Default value: `^[a-zA-Z0-9_]+$`.
|
||||
- `CORSAllowOrigins`: List of origins that may access Drasl API routes. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin. Necessary for allowing browsers to access the Drasl API. Set to `["*"]` to allow all origins. Array of strings. Example value: `["https://front-end.example.com"]`. Default value: `[]`.
|
||||
- `PlayerUUIDGeneration`: How to generate UUIDs for new players. Must be either `"random"` or `"offline"`. `"random"` generates a new random Version 4 UUID. `"offline"` means the player's UUID will be generated from the player's name using the same algorithm Minecraft uses to derive player UUIDs on `online-mode=false` servers. `PlayerUUIDGeneration = "offline"` is useful for migrating `online-mode=false` servers to Drasl since it lets player UUIDs (and thus inventories, permissions, etc.) remain the same when switching from `online-mode=false` to `online-mode=true`. Note: if a player's name is changed, their UUID will not change, even with `PlayerUUIDGeneration = "offline"`. String. Default value: `"random"`.
|
||||
|
@ -8,16 +8,14 @@ See [configuration.md](./configuration.md) for detailed documentation of each co
|
||||
### Example 1: Basic, minimal setup
|
||||
|
||||
- Private and standalone: does not interact with any other API servers
|
||||
- Registering a new account requires an invite from an admin
|
||||
- Users can choose their player's UUID when they register, useful for migrating from Mojang accounts
|
||||
- Registering a new account requires an invite from an admin (`RegistrationNewPlayer.RequireInvite`)
|
||||
- Seamless migration from `online-mode=false` servers: UUIDs of new players will be derived from their player name using the same algorithm used by Minecraft to derive player UUIDs in `online-mode=false` servers (`PlayerUUIDGeneration`)
|
||||
|
||||
```
|
||||
Domain = "drasl.example.com" # CHANGE ME!
|
||||
BaseURL = "https://drasl.example.com" # CHANGE ME!
|
||||
DefaultAdmins = ["myusername"] # CHANGE ME!
|
||||
|
||||
[CreateNewPlayer]
|
||||
AllowChoosingUUID = true
|
||||
PlayerUUIDGeneration = "offline"
|
||||
|
||||
[RegistrationNewPlayer]
|
||||
Allow = true
|
||||
|
@ -432,6 +432,9 @@ msgstr "Crear un nuevo jugador con un UUID aleatorio:"
|
||||
msgid "Player UUID (leave blank for random)"
|
||||
msgstr "UUID del jugador (déjelo en blanco para uno aleatorio)"
|
||||
|
||||
msgid "Player UUID (leave blank for offline UUID)"
|
||||
msgstr "UUID del jugador (déjelo en blanco para usar el UUID offline)"
|
||||
|
||||
msgid "Import a player from %s"
|
||||
msgstr "Importar un jugador desde %s"
|
||||
|
||||
|
5
model.go
5
model.go
@ -25,6 +25,11 @@ const (
|
||||
TextureTypeCape string = "cape"
|
||||
)
|
||||
|
||||
const (
|
||||
PlayerUUIDGenerationRandom string = "random"
|
||||
PlayerUUIDGenerationOffline string = "offline"
|
||||
)
|
||||
|
||||
func MakeNullString(s *string) sql.NullString {
|
||||
if s == nil {
|
||||
return sql.NullString{Valid: false}
|
||||
|
@ -157,7 +157,11 @@ func (app *App) CreatePlayer(
|
||||
}
|
||||
|
||||
if chosenUUID == nil {
|
||||
playerUUID = uuid.New().String()
|
||||
var err error
|
||||
playerUUID, err = app.NewPlayerUUID(playerName)
|
||||
if err != nil {
|
||||
return Player{}, err
|
||||
}
|
||||
} else {
|
||||
if !app.Config.CreateNewPlayer.AllowChoosingUUID && !callerIsAdmin {
|
||||
return Player{}, NewBadRequestUserError("Choosing a UUID is not allowed.")
|
||||
|
5
user.go
5
user.go
@ -189,7 +189,10 @@ func (app *App) CreateUser(
|
||||
}
|
||||
|
||||
if chosenUUID == nil {
|
||||
playerUUID = uuid.New().String()
|
||||
playerUUID, err = app.NewPlayerUUID(*playerName)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
} else {
|
||||
if !app.Config.CreateNewPlayer.AllowChoosingUUID && !callerIsAdmin {
|
||||
return User{}, NewBadRequestUserError("Choosing a UUID is not allowed.")
|
||||
|
@ -39,11 +39,7 @@
|
||||
{{ $dividerNeeded = false }}
|
||||
{{ end }}
|
||||
<h3>{{ call .T "Create a player" }}</h3>
|
||||
{{ if .App.Config.CreateNewPlayer.AllowChoosingUUID }}
|
||||
<p>{{ call .T "Complete registration by creating a new player:" }}</p>
|
||||
{{ else }}
|
||||
<p>{{ call .T "Complete registration by creating a new player with a random UUID:" }}</p>
|
||||
{{ end }}
|
||||
<p>{{ call .T "Complete registration by creating a new player:" }}</p>
|
||||
<form action="{{ .App.FrontEndURL }}/web/register" method="post">
|
||||
<input
|
||||
required
|
||||
@ -69,7 +65,7 @@
|
||||
class="long"
|
||||
type="text"
|
||||
name="uuid"
|
||||
placeholder="{{ call .T "Player UUID (leave blank for random)" }}"
|
||||
placeholder="{{ if eq .App.Config.PlayerUUIDGeneration "offline" }}{{ call .T "Player UUID (leave blank for offline UUID)" }}{{ else }}{{ call .T "Player UUID (leave blank for random)" }}{{ end }}"
|
||||
pattern="^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$"
|
||||
/>
|
||||
</p>
|
||||
|
@ -64,7 +64,7 @@
|
||||
class="long"
|
||||
type="text"
|
||||
name="uuid"
|
||||
placeholder="{{ call .T "Player UUID (leave blank for random)" }}"
|
||||
placeholder="{{ if eq .App.Config.PlayerUUIDGeneration "offline" }}{{ call .T "Player UUID (leave blank for offline UUID)" }}{{ else }}{{ call .T "Player UUID (leave blank for random)" }}{{ end }}"
|
||||
pattern="^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$"
|
||||
/>
|
||||
</p>
|
||||
|
@ -142,7 +142,7 @@
|
||||
class="long"
|
||||
type="text"
|
||||
name="playerUuid"
|
||||
placeholder="{{ call .T "Player UUID (leave blank for random)" }}"
|
||||
placeholder="{{ if eq .App.Config.PlayerUUIDGeneration "offline" }}{{ call .T "Player UUID (leave blank for offline UUID)" }}{{ else }}{{ call .T "Player UUID (leave blank for random)" }}{{ end }}"
|
||||
pattern="^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$"
|
||||
/>
|
||||
{{ end }}
|
||||
|
Loading…
x
Reference in New Issue
Block a user