Upload game save
This commit is contained in:
@@ -2,10 +2,13 @@ package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"opensavecloudserver/database"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type NewGameInfo struct {
|
||||
@@ -48,6 +51,27 @@ func CreateGame(w http.ResponseWriter, r *http.Request) {
|
||||
ok(game, w, r)
|
||||
}
|
||||
|
||||
func GameInfoByID(w http.ResponseWriter, r *http.Request) {
|
||||
userId, err := userIdFromContext(r.Context())
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
return
|
||||
}
|
||||
queryId := chi.URLParam(r, "id")
|
||||
id, err := strconv.Atoi(queryId)
|
||||
if err != nil {
|
||||
badRequest("Game ID missing or not an int", w, r)
|
||||
return
|
||||
}
|
||||
game, err := database.GameInfoById(userId, id)
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
ok(game, w, r)
|
||||
}
|
||||
|
||||
func AskForUpload(w http.ResponseWriter, r *http.Request) {
|
||||
userId, err := userIdFromContext(r.Context())
|
||||
if err != nil {
|
||||
@@ -74,3 +98,47 @@ func AskForUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
ok(token, w, r)
|
||||
}
|
||||
|
||||
func UploadSave(w http.ResponseWriter, r *http.Request) {
|
||||
userId, err := userIdFromContext(r.Context())
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
return
|
||||
}
|
||||
gameId, err := gameIdFromContext(r.Context())
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
return
|
||||
}
|
||||
defer database.UnlockGame(gameId)
|
||||
game, err := database.GameInfoById(userId, gameId)
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
return
|
||||
}
|
||||
file, _, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
err = database.UploadSave(file, game)
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
err = database.UpdateGameRevision(game)
|
||||
if err != nil {
|
||||
internalServerError(w, r)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
payload := &successMessage{
|
||||
Message: "Game uploaded",
|
||||
Timestamp: time.Now(),
|
||||
Status: 200,
|
||||
}
|
||||
ok(payload, w, r)
|
||||
}
|
||||
|
||||
@@ -9,11 +9,15 @@ import (
|
||||
"net/http"
|
||||
"opensavecloudserver/authentication"
|
||||
"opensavecloudserver/config"
|
||||
"opensavecloudserver/database"
|
||||
)
|
||||
|
||||
type ContextKey string
|
||||
|
||||
const UserIdKey ContextKey = "userId"
|
||||
const (
|
||||
UserIdKey ContextKey = "userId"
|
||||
GameIdKey ContextKey = "gameId"
|
||||
)
|
||||
|
||||
// Serve start the http server
|
||||
func Serve() {
|
||||
@@ -30,11 +34,17 @@ func Serve() {
|
||||
r.Route("/system", func(systemRouter chi.Router) {
|
||||
systemRouter.Get("/information", Information)
|
||||
})
|
||||
r.Group(func(secureRouter chi.Router) {
|
||||
r.Route("/game", func(secureRouter chi.Router) {
|
||||
secureRouter.Use(authMiddleware)
|
||||
secureRouter.Post("/game/create", CreateGame)
|
||||
secureRouter.Post("/game/upload/init", AskForUpload)
|
||||
secureRouter.Post("/create", CreateGame)
|
||||
secureRouter.Get("/{id}", GameInfoByID)
|
||||
secureRouter.Post("/upload/init", AskForUpload)
|
||||
secureRouter.Group(func(uploadRouter chi.Router) {
|
||||
uploadRouter.Use(uploadMiddleware)
|
||||
uploadRouter.Post("/upload", UploadSave)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
log.Println("Server is listening...")
|
||||
@@ -44,7 +54,7 @@ func Serve() {
|
||||
}
|
||||
}
|
||||
|
||||
// authMiddleware filter the request
|
||||
// authMiddleware check the authentication token before accessing to the resource
|
||||
func authMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
header := r.Header.Get("Authorization")
|
||||
@@ -63,6 +73,22 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
// uploadMiddleware check the upload key before allowing to upload a file
|
||||
func uploadMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
header := r.Header.Get("X-Upload-Key")
|
||||
if len(header) > 0 {
|
||||
if gameId, ok := database.CheckUploadToken(header); ok {
|
||||
ctx := context.WithValue(r.Context(), GameIdKey, gameId)
|
||||
r = r.WithContext(ctx)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
unauthorized(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func userIdFromContext(ctx context.Context) (int, error) {
|
||||
if userId, ok := ctx.Value(UserIdKey).(int); ok {
|
||||
return userId, nil
|
||||
@@ -70,6 +96,13 @@ func userIdFromContext(ctx context.Context) (int, error) {
|
||||
return 0, errors.New("userId not found in context")
|
||||
}
|
||||
|
||||
func gameIdFromContext(ctx context.Context) (int, error) {
|
||||
if gameId, ok := ctx.Value(GameIdKey).(int); ok {
|
||||
return gameId, nil
|
||||
}
|
||||
return 0, errors.New("gameId not found in context")
|
||||
}
|
||||
|
||||
func recovery(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
|
||||
Reference in New Issue
Block a user