forked from TripwireTeam/tripwire
skins work!!!!!!!!!!!!
This commit is contained in:
parent
c266a5d9fd
commit
77ce652e28
|
@ -3,3 +3,4 @@ secrets.go
|
||||||
tripwire
|
tripwire
|
||||||
skins/
|
skins/
|
||||||
capes/
|
capes/
|
||||||
|
keys/
|
||||||
|
|
22
auth.go
22
auth.go
|
@ -1,13 +1,18 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
func rootEndpoint(w http.ResponseWriter, r *http.Request) {
|
func rootEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, YggdrasilInfo{
|
skinDomains := []string{
|
||||||
|
config.BaseUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
response := YggdrasilInfo{
|
||||||
Status: "OK",
|
Status: "OK",
|
||||||
RuntimeMode: "productionMode",
|
RuntimeMode: "productionMode",
|
||||||
AppAuthor: "Tripwire Team",
|
AppAuthor: "Tripwire Team",
|
||||||
|
@ -16,7 +21,20 @@ func rootEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
AppName: "tripwire.yggdrasil",
|
AppName: "tripwire.yggdrasil",
|
||||||
ImplVersion: "5.2.0",
|
ImplVersion: "5.2.0",
|
||||||
AppOwner: "Who knows?",
|
AppOwner: "Who knows?",
|
||||||
})
|
|
||||||
|
//Used by authlib-injector
|
||||||
|
SkinDomains: skinDomains,
|
||||||
|
}
|
||||||
|
|
||||||
|
if publicKey != nil {
|
||||||
|
pubkey, err := x509.MarshalPKIXPublicKey(publicKey)
|
||||||
|
if err == nil {
|
||||||
|
pubKeyString := string(encodePem(pubkey, "PUBLIC KEY"))
|
||||||
|
response.PublicKey = &pubKeyString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendJSON(w, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
func authenticateEndpoint(w http.ResponseWriter, r *http.Request) {
|
func authenticateEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
BaseUrl string `yaml:"baseUrl"`
|
BaseUrl string `yaml:"baseUrl"`
|
||||||
|
Protocol string `yaml:"protocol"`
|
||||||
DebugMode bool `yaml:"debugMode"`
|
DebugMode bool `yaml:"debugMode"`
|
||||||
MaxTextureSize int `yaml:"maxTextureSize"`
|
MaxTextureSize int `yaml:"maxTextureSize"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# The URL the Tripwire instance is hosted on.
|
# The primary domain the Tripwire instance is hosted on.
|
||||||
baseUrl: "http://localhost:10000"
|
# It shouldn't be a local IP in production.
|
||||||
|
baseUrl: "localhost:10000"
|
||||||
|
|
||||||
|
# The protocol to be used for Tripwire
|
||||||
|
protocol: "http://"
|
||||||
|
|
||||||
# Show debug output (if unsure, set to false)
|
# Show debug output (if unsure, set to false)
|
||||||
debugMode: true
|
debugMode: true
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -8,3 +8,8 @@ require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.13
|
github.com/mattn/go-sqlite3 v1.14.13
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb // indirect
|
||||||
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -4,6 +4,10 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/mattn/go-sqlite3 v1.14.13 h1:1tj15ngiFfcZzii7yd82foL+ks+ouQcj8j/TPq3fk1I=
|
github.com/mattn/go-sqlite3 v1.14.13 h1:1tj15ngiFfcZzii7yd82foL+ks+ouQcj8j/TPq3fk1I=
|
||||||
github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
|
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
|
||||||
|
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
|
||||||
|
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
|
||||||
|
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
17
main.go
17
main.go
|
@ -38,11 +38,6 @@ func handleRequests() {
|
||||||
r.Use(logger)
|
r.Use(logger)
|
||||||
r.NotFoundHandler = http.HandlerFunc(notfoundlogger)
|
r.NotFoundHandler = http.HandlerFunc(notfoundlogger)
|
||||||
|
|
||||||
err := loadConfig()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Failed to load config.yaml:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: make this cleaner if possible
|
// todo: make this cleaner if possible
|
||||||
registerAuthEndpoints(r)
|
registerAuthEndpoints(r)
|
||||||
registerSessionEndpoints(r)
|
registerSessionEndpoints(r)
|
||||||
|
@ -53,10 +48,22 @@ func handleRequests() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if len(os.Args) > 1 && os.Args[1] == "gen-keys" {
|
||||||
|
genKeys()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("Tripwire initializing...")
|
log.Println("Tripwire initializing...")
|
||||||
os.Mkdir("skins", 0755)
|
os.Mkdir("skins", 0755)
|
||||||
os.Mkdir("capes", 0755)
|
os.Mkdir("capes", 0755)
|
||||||
|
|
||||||
|
err := loadConfig()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed to load config.yaml:", err)
|
||||||
|
}
|
||||||
|
|
||||||
initDB()
|
initDB()
|
||||||
|
initKeys()
|
||||||
|
|
||||||
handleRequests()
|
handleRequests()
|
||||||
|
|
||||||
|
|
42
session.go
42
session.go
|
@ -12,6 +12,20 @@ import (
|
||||||
|
|
||||||
func profileEndpoint(w http.ResponseWriter, r *http.Request) {
|
func profileEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := mux.Vars(r)["uuid"]
|
uuid := mux.Vars(r)["uuid"]
|
||||||
|
query := r.URL.Query()
|
||||||
|
|
||||||
|
if len(uuid) == 32 {
|
||||||
|
uuid = growUUID(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(uuid) != 36 {
|
||||||
|
sendError(w, YggError{
|
||||||
|
Code: 400,
|
||||||
|
Error: "Bad Request",
|
||||||
|
ErrorMessage: "Invalid UUID.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
exists, err := playerExistsByUUID(uuid)
|
exists, err := playerExistsByUUID(uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -33,7 +47,9 @@ func profileEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := generateProfileResponse(uuid, player.Username)
|
signed := query.Has("unsigned") && query.Get("unsigned") == "false"
|
||||||
|
|
||||||
|
response, err := generateProfileResponse(uuid, player.Username, signed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err)
|
handleError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -55,7 +71,7 @@ func hasJoinedEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := generateProfileResponse(player.UUID, params.Get("username"))
|
response, err := generateProfileResponse(player.UUID, params.Get("username"), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(w, err)
|
handleError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -100,10 +116,10 @@ func registerSessionEndpoints(r *mux.Router) {
|
||||||
r.HandleFunc(prefix+"/session/minecraft/hasJoined", hasJoinedEndpoint).Methods("GET")
|
r.HandleFunc(prefix+"/session/minecraft/hasJoined", hasJoinedEndpoint).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateProfileResponse(uuid string, username string) (ProfileResponse, error) {
|
func generateProfileResponse(uuid string, username string, signed bool) (ProfileResponse, error) {
|
||||||
// todo: make this more visually appealing if possible
|
// todo: make this more visually appealing if possible
|
||||||
skin := SkinTexture{}
|
skin := SkinTexture{}
|
||||||
skin.Url = config.BaseUrl + "/getTexture/" + uuid + "?type=skin"
|
skin.Url = config.Protocol + config.BaseUrl + "/getTexture/" + uuid + "?type=skin"
|
||||||
skin.Metadata = SkinMetadata{}
|
skin.Metadata = SkinMetadata{}
|
||||||
skin.Metadata.Model = "default"
|
skin.Metadata.Model = "default"
|
||||||
|
|
||||||
|
@ -116,7 +132,7 @@ func generateProfileResponse(uuid string, username string) (ProfileResponse, err
|
||||||
_, err := os.Stat("capes/" + uuid + ".png")
|
_, err := os.Stat("capes/" + uuid + ".png")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cape := &Texture{}
|
cape := &Texture{}
|
||||||
cape.Url = config.BaseUrl + "/getTexture/" + uuid + "?type=cape"
|
cape.Url = config.Protocol + config.BaseUrl + "/getTexture/" + uuid + "?type=cape"
|
||||||
textures.Textures.Cape = cape
|
textures.Textures.Cape = cape
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +140,7 @@ func generateProfileResponse(uuid string, username string) (ProfileResponse, err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ProfileResponse{}, err
|
return ProfileResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
encodedTextures := base64.StdEncoding.EncodeToString(marshalledTextures)
|
encodedTextures := base64.StdEncoding.EncodeToString(marshalledTextures)
|
||||||
|
|
||||||
response := ProfileResponse{}
|
response := ProfileResponse{}
|
||||||
|
@ -135,6 +152,19 @@ func generateProfileResponse(uuid string, username string) (ProfileResponse, err
|
||||||
Value: encodedTextures,
|
Value: encodedTextures,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if signed && privateKey != nil {
|
||||||
|
signedTextures, err := signWithPrivateKey(string(encodedTextures))
|
||||||
|
if err != nil {
|
||||||
|
return ProfileResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b64 := make([]byte, base64.StdEncoding.EncodedLen(len(signedTextures)))
|
||||||
|
base64.StdEncoding.Encode(b64, signedTextures)
|
||||||
|
|
||||||
|
stringified := string(b64)
|
||||||
|
response.Properties[0].Signature = &stringified
|
||||||
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +174,7 @@ func shrinkUUID(uuid string) string {
|
||||||
|
|
||||||
func growUUID(uuid string) string {
|
func growUUID(uuid string) string {
|
||||||
if len(uuid) == 32 {
|
if len(uuid) == 32 {
|
||||||
return uuid[0:7] + "-" + uuid[8:11] + "-" + uuid[12:15] + "-" + uuid[16:19] + "-" + uuid[20:31]
|
return uuid[0:8] + "-" + uuid[8:12] + "-" + uuid[12:16] + "-" + uuid[16:20] + "-" + uuid[20:32]
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
39
sha.go
39
sha.go
|
@ -1,39 +0,0 @@
|
||||||
// Ripped from https://gist.github.com/toqueteos/5372776
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha1"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func authDigest(s string) string {
|
|
||||||
h := sha1.New()
|
|
||||||
io.WriteString(h, s)
|
|
||||||
hash := h.Sum(nil)
|
|
||||||
|
|
||||||
negative := (hash[0] & 0x80) == 0x80
|
|
||||||
if negative {
|
|
||||||
hash = twosComplement(hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
res := strings.TrimLeft(hex.EncodeToString(hash), "0")
|
|
||||||
if negative {
|
|
||||||
res = "-" + res
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func twosComplement(p []byte) []byte {
|
|
||||||
carry := true
|
|
||||||
for i := len(p) - 1; i >= 0; i-- {
|
|
||||||
p[i] = byte(^p[i])
|
|
||||||
if carry {
|
|
||||||
carry = p[i] == 0xff
|
|
||||||
p[i]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var publicKey *rsa.PublicKey
|
||||||
|
var privateKey *rsa.PrivateKey
|
||||||
|
|
||||||
|
func initKeys() {
|
||||||
|
pubKeyBytes, err1 := os.ReadFile("keys/public.key")
|
||||||
|
privKeyBytes, err2 := os.ReadFile("keys/private.key")
|
||||||
|
if err1 != nil || err2 != nil {
|
||||||
|
log.Println("WARNING: At least one key half could not be opened, players will not have any textures!")
|
||||||
|
log.Println("Try generating a keypair by running \"tripwire gen-keys\".")
|
||||||
|
if config.DebugMode {
|
||||||
|
log.Println(err1)
|
||||||
|
log.Println(err2)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pubDer, _ := pem.Decode(pubKeyBytes)
|
||||||
|
privDer, _ := pem.Decode(privKeyBytes)
|
||||||
|
|
||||||
|
pubKey, err1 := x509.ParsePKIXPublicKey(pubDer.Bytes)
|
||||||
|
privKey, err2 := x509.ParsePKCS8PrivateKey(privDer.Bytes)
|
||||||
|
if err1 != nil || err2 != nil {
|
||||||
|
log.Println("WARNING: At least one key half could not be loaded, players will not have any textures!")
|
||||||
|
log.Println("Try generating a keypair by running \"tripwire gen-keys\".")
|
||||||
|
if config.DebugMode {
|
||||||
|
log.Println(err1)
|
||||||
|
log.Println(err2)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
publicKey = pubKey.(*rsa.PublicKey)
|
||||||
|
privateKey = privKey.(*rsa.PrivateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genKeys() {
|
||||||
|
os.Mkdir("keys", 0700)
|
||||||
|
_, err1 := os.Stat("keys/public.key")
|
||||||
|
_, err2 := os.Stat("keys/public.key")
|
||||||
|
if err1 == nil || err2 == nil {
|
||||||
|
log.Println(
|
||||||
|
"Error: At least one key half is already present. " +
|
||||||
|
"If you are having errors reading the key " +
|
||||||
|
"files, you have likely incorrectly configured " +
|
||||||
|
"folder permissions.",
|
||||||
|
)
|
||||||
|
log.Println(
|
||||||
|
"If you would like to generate a new keypair anyway, " +
|
||||||
|
"delete the keys folder and run this command again.",
|
||||||
|
)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if !errors.Is(err1, fs.ErrNotExist) || !errors.Is(err2, fs.ErrNotExist) {
|
||||||
|
log.Fatalln(
|
||||||
|
"Error: Could not access keys folder. " +
|
||||||
|
"Try recreating the folder, or running this command " +
|
||||||
|
"as a user that has permissions to view it.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
log.Println("Generating RSA keypair at 4096 bits...")
|
||||||
|
privkey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pubkeygen, err := x509.MarshalPKIXPublicKey(&privkey.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(
|
||||||
|
"keys/public.key",
|
||||||
|
encodePem(pubkeygen, "PUBLIC KEY"),
|
||||||
|
0600,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
privkeygen, err := x509.MarshalPKCS8PrivateKey(privkey)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(
|
||||||
|
"keys/private.key",
|
||||||
|
encodePem(privkeygen, "PRIVATE KEY"),
|
||||||
|
0600,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
log.Println("Done!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signWithPrivateKey(value string) ([]byte, error) {
|
||||||
|
hasher := sha1.New()
|
||||||
|
hasher.Write([]byte(value))
|
||||||
|
|
||||||
|
return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, hasher.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodePem(in []byte, name string) []byte {
|
||||||
|
return pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: name,
|
||||||
|
Bytes: in,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
23
types.go
23
types.go
|
@ -67,19 +67,22 @@ type PlayerData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type YggdrasilInfo struct {
|
type YggdrasilInfo struct {
|
||||||
Status string `json:"Status"`
|
Status string `json:"Status"`
|
||||||
RuntimeMode string `json:"Runtime-Mode"`
|
RuntimeMode string `json:"Runtime-Mode"`
|
||||||
AppAuthor string `json:"Application-Author"`
|
AppAuthor string `json:"Application-Author"`
|
||||||
AppDescription string `json:"Application-Description"`
|
AppDescription string `json:"Application-Description"`
|
||||||
SpecVersion string `json:"Specification-Version"`
|
SpecVersion string `json:"Specification-Version"`
|
||||||
AppName string `json:"Application-Name"`
|
AppName string `json:"Application-Name"`
|
||||||
ImplVersion string `json:"Implementation-Version"`
|
ImplVersion string `json:"Implementation-Version"`
|
||||||
AppOwner string `json:"Application-Owner"`
|
AppOwner string `json:"Application-Owner"`
|
||||||
|
SkinDomains []string `json:"skinDomains"`
|
||||||
|
PublicKey *string `json:"signaturePublickey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Property struct {
|
type Property struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
|
Signature *string `json:"signature"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProfileResponse struct {
|
type ProfileResponse struct {
|
||||||
|
|
21
web.go
21
web.go
|
@ -69,7 +69,7 @@ func logInEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getResourceEndpoint(w http.ResponseWriter, r *http.Request) {
|
func getTextureEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := mux.Vars(r)["uuid"]
|
uuid := mux.Vars(r)["uuid"]
|
||||||
query := r.URL.Query()
|
query := r.URL.Query()
|
||||||
if !query.Has("type") {
|
if !query.Has("type") {
|
||||||
|
@ -107,7 +107,7 @@ func getResourceEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write(skin)
|
w.Write(skin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setResourceEndpoint(w http.ResponseWriter, r *http.Request) {
|
func setTextureEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := mux.Vars(r)["uuid"]
|
uuid := mux.Vars(r)["uuid"]
|
||||||
query := r.URL.Query()
|
query := r.URL.Query()
|
||||||
if !query.Has("type") {
|
if !query.Has("type") {
|
||||||
|
@ -124,6 +124,19 @@ func setResourceEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(uuid) == 32 {
|
||||||
|
uuid = growUUID(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(uuid) != 36 {
|
||||||
|
sendError(w, YggError{
|
||||||
|
Code: 400,
|
||||||
|
Error: "Bad Request",
|
||||||
|
ErrorMessage: "Invalid UUID.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
r.ParseMultipartForm(int64(config.MaxTextureSize))
|
r.ParseMultipartForm(int64(config.MaxTextureSize))
|
||||||
|
|
||||||
token := r.FormValue("token")
|
token := r.FormValue("token")
|
||||||
|
@ -196,6 +209,6 @@ func registerWebEndpoints(r *mux.Router) {
|
||||||
r.PathPrefix(webDir).
|
r.PathPrefix(webDir).
|
||||||
Handler(http.StripPrefix(webDir, http.FileServer(http.Dir("."+webDir))))
|
Handler(http.StripPrefix(webDir, http.FileServer(http.Dir("."+webDir))))
|
||||||
|
|
||||||
r.HandleFunc("/getTexture/{uuid}", getResourceEndpoint).Methods("GET")
|
r.HandleFunc("/getTexture/{uuid}", getTextureEndpoint).Methods("GET")
|
||||||
r.HandleFunc("/setTexture/{uuid}", setResourceEndpoint).Methods("POST")
|
r.HandleFunc("/setTexture/{uuid}", setTextureEndpoint).Methods("POST")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue