3 Commits

Author SHA1 Message Date
128cdcee52 feat: support additional /publickeys endpoint 2023-10-06 16:11:57 +08:00
5a9e73d4f2 add missing assets 2023-09-27 23:41:34 +08:00
a77942621e 分离静态文件 2023-09-27 23:41:18 +08:00
24 changed files with 42 additions and 17 deletions

View File

@@ -45,14 +45,14 @@ jobs:
- name: Create ZIP archive - name: Create ZIP archive
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
run: | run: |
cp -v ./config_example.ini ./build || exit 1 cp -v ./config_example.ini ./assets ./build/ || exit 1
pushd build || exit 1 pushd build || exit 1
ls -1 yggdrasil-* | while read LINE; do ls -1 yggdrasil-* | while read LINE; do
PREFIX="${LINE%.*}" PREFIX="${LINE%.*}"
SUFFIX="$(echo "$LINE" | grep -osE '\.\w+' || printf '')" SUFFIX="$(echo "$LINE" | grep -osE '\.\w+' || printf '')"
cp -v "$LINE" "yggdrasil$SUFFIX" cp -v "$LINE" "yggdrasil$SUFFIX"
FILE="../$PREFIX.zip" FILE="../$PREFIX.zip"
zip -9v "$FILE" "yggdrasil$SUFFIX" *.ini zip -9v "$FILE" "yggdrasil$SUFFIX" *.ini assets
DGST="$FILE.dgst" DGST="$FILE.dgst"
openssl dgst -md5 "$FILE" | sed 's/([^)]*)//g' >>"$DGST" openssl dgst -md5 "$FILE" | sed 's/([^)]*)//g' >>"$DGST"
openssl dgst -sha1 "$FILE" | sed 's/([^)]*)//g' >>"$DGST" openssl dgst -sha1 "$FILE" | sed 's/([^)]*)//g' >>"$DGST"

View File

@@ -10,6 +10,7 @@ COPY "build/yggdrasil-${TARGETOS}-${TARGETARCH}" /app/yggdrasil
EXPOSE 8080 EXPOSE 8080
VOLUME /app/data VOLUME /app/data
COPY assets /app/data/assets/
WORKDIR /app/data WORKDIR /app/data
ENTRYPOINT ["/app/yggdrasil"] ENTRYPOINT ["/app/yggdrasil"]

View File

@@ -10,7 +10,7 @@ PACKAGE_NAME = yggdrasil.tar.gz
default: $(BINARY) default: $(BINARY)
$(BINARY): $(BINARY):assets
$(GO_BUILD) -tags='nomsgpack,sqlite,mysql' -o $(BINARY) $(GO_BUILD) -tags='nomsgpack,sqlite,mysql' -o $(BINARY)
get: get:
@@ -23,7 +23,7 @@ assets:
cp -r frontend/dist/. assets/ cp -r frontend/dist/. assets/
package:$(BINARY) package:$(BINARY)
tar -zcf $(PACKAGE_NAME) $(BINARY) config_example.ini tar -zcf $(PACKAGE_NAME) $(BINARY) config_example.ini assets
clean: clean:
-$(GO_CLEAN) -$(GO_CLEAN)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

11
main.go
View File

@@ -22,13 +22,11 @@ import (
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"embed"
"encoding/pem" "encoding/pem"
"errors" "errors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"gorm.io/gorm" "gorm.io/gorm"
"io/fs"
"log" "log"
"net/http" "net/http"
"os" "os"
@@ -40,9 +38,6 @@ import (
"yggdrasil-go/util" "yggdrasil-go/util"
) )
//go:embed assets/*
var f embed.FS
type MetaCfg struct { type MetaCfg struct {
ServerName string `ini:"server_name"` ServerName string `ini:"server_name"`
ImplementationName string `ini:"implementation_name"` ImplementationName string `ini:"implementation_name"`
@@ -139,11 +134,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
router.InitRouters(r, db, &serverMeta, meta.SkinRootUrl) router.InitRouters(r, db, &serverMeta, meta.SkinRootUrl)
assetsFs, err := fs.Sub(f, "assets") r.Static("/profile", "assets")
if err != nil {
log.Fatal(err)
}
r.StaticFS("/profile", http.FS(assetsFs))
srv := &http.Server{ srv := &http.Server{
Addr: serverCfg.ServerAddress, Addr: serverCfg.ServerAddress,
Handler: r, Handler: r,

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2022. Gardel <sunxinao@hotmail.com> and contributors * Copyright (C) 2022-2023. Gardel <sunxinao@hotmail.com> and contributors
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@@ -18,8 +18,11 @@
package router package router
import ( import (
"encoding/base64"
"encoding/pem"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"yggdrasil-go/util"
) )
type MetaInfo struct { type MetaInfo struct {
@@ -42,17 +45,31 @@ type ServerMeta struct {
SignaturePublickey string `json:"signaturePublickey"` SignaturePublickey string `json:"signaturePublickey"`
} }
type KeyPair struct {
PrivateKey string `json:"privateKey,omitempty"`
PublicKey string `json:"publicKey,omitempty"`
}
type PublicKeys struct {
ProfilePropertyKeys []KeyPair `json:"profilePropertyKeys,omitempty"`
PlayerCertificateKeys []KeyPair `json:"playerCertificateKeys,omitempty"`
}
type HomeRouter interface { type HomeRouter interface {
Home(c *gin.Context) Home(c *gin.Context)
PublicKeys(c *gin.Context)
} }
type homeRouterImpl struct { type homeRouterImpl struct {
serverMeta ServerMeta serverMeta ServerMeta
myPubKey KeyPair
} }
func NewHomeRouter(meta *ServerMeta) HomeRouter { func NewHomeRouter(meta *ServerMeta) HomeRouter {
signaturePubKey, _ := pem.Decode([]byte(meta.SignaturePublickey))
homeRouter := homeRouterImpl{ homeRouter := homeRouterImpl{
serverMeta: *meta, serverMeta: *meta,
myPubKey: KeyPair{PublicKey: base64.StdEncoding.EncodeToString(signaturePubKey.Bytes)},
} }
return &homeRouter return &homeRouter
} }
@@ -61,3 +78,15 @@ func NewHomeRouter(meta *ServerMeta) HomeRouter {
func (h *homeRouterImpl) Home(c *gin.Context) { func (h *homeRouterImpl) Home(c *gin.Context) {
c.JSON(http.StatusOK, h.serverMeta) c.JSON(http.StatusOK, h.serverMeta)
} }
func (h *homeRouterImpl) PublicKeys(c *gin.Context) {
publicKeys := PublicKeys{}
err := util.GetObject("https://api.minecraftservices.com/publickeys", &publicKeys)
if err != nil {
util.HandleError(c, err)
return
}
publicKeys.ProfilePropertyKeys = append(publicKeys.ProfilePropertyKeys, h.myPubKey)
publicKeys.PlayerCertificateKeys = append(publicKeys.PlayerCertificateKeys, h.myPubKey)
c.JSON(http.StatusOK, publicKeys)
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2022. Gardel <sunxinao@hotmail.com> and contributors * Copyright (C) 2022-2023. Gardel <sunxinao@hotmail.com> and contributors
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@@ -72,5 +72,9 @@ func InitRouters(router *gin.Engine, db *gorm.DB, meta *ServerMeta, skinRootUrl
api.DELETE("/user/profile/:uuid/:textureType", textureRouter.DeleteTexture) api.DELETE("/user/profile/:uuid/:textureType", textureRouter.DeleteTexture)
api.GET("/users/profiles/minecraft/:username", userRouter.UsernameToUUID) api.GET("/users/profiles/minecraft/:username", userRouter.UsernameToUUID)
} }
router.POST("/minecraftservices/player/certificates", userRouter.ProfileKey) minecraftservices := router.Group("/minecraftservices")
{
minecraftservices.POST("/player/certificates", userRouter.ProfileKey)
minecraftservices.GET("/publickeys", homeRouter.PublicKeys)
}
} }