diff --git a/.env b/.devcontainer/.env
similarity index 100%
rename from .env
rename to .devcontainer/.env
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000..a02e4da
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1 @@
+FROM gitrepo.ru/neonxp/devcontainer:latest
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..e1e7f8d
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,26 @@
+{
+ "name": "Go",
+ "dockerComposeFile": "./docker-compose.yml",
+ "service": "app",
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
+ "forwardPorts": [5432, 5173, 8000],
+ "remoteUser": "vscode",
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-vscode.makefile-tools",
+ "redhat.vscode-yaml",
+ "humao.rest-client",
+ "mtxr.sqltools",
+ "mtxr.sqltools-driver-pg",
+ "codezombiech.gitignore",
+ "ms-azuretools.vscode-docker"
+ ]
+ }
+ },
+ "postCreateCommand": "go mod download",
+ "features": {
+ "https://gitrepo.ru/api/packages/NeonXP/generic/features/latest/devcontainer-feature-common-utils.tgz": {},
+ "https://gitrepo.ru/api/packages/NeonXP/generic/features/latest/devcontainer-feature-go.tgz": {}
+ }
+}
diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
new file mode 100644
index 0000000..4a959ae
--- /dev/null
+++ b/.devcontainer/docker-compose.yml
@@ -0,0 +1,24 @@
+version: '3.8'
+
+volumes:
+ postgres-data:
+
+services:
+ app:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ env_file:
+ - .env
+ volumes:
+ - ../..:/workspaces:cached
+ command: sleep infinity
+ network_mode: service:db
+
+ db:
+ image: postgres:15-alpine3.17
+ restart: unless-stopped
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+ env_file:
+ - .env
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..f33a02c
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for more information:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+# https://containers.dev/guide/dependabot
+
+version: 2
+updates:
+ - package-ecosystem: "devcontainers"
+ directory: "/"
+ schedule:
+ interval: weekly
diff --git a/.vscode/launch.json b/.vscode/launch.json
index eac9d30..aaded20 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/",
- "envFile": "${workspaceFolder}/.env"
+ "envFile": "${workspaceFolder}/.devcontainer/.env"
}
]
}
\ No newline at end of file
diff --git a/api/openapi.yaml b/api/openapi.yaml
index b912361..acdf281 100644
--- a/api/openapi.yaml
+++ b/api/openapi.yaml
@@ -20,7 +20,16 @@ paths:
post:
security: []
requestBody:
- $ref: "#/components/requestBodies/login"
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ email:
+ type: string
+ password:
+ type: string
+ required: [email, password]
responses:
200:
$ref: "#/components/responses/userResponse"
@@ -30,7 +39,20 @@ paths:
post:
security: []
requestBody:
- $ref: "#/components/requestBodies/register"
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ username:
+ type: string
+ email:
+ type: string
+ password:
+ type: string
+ password2:
+ type: string
+ required: [username, email, password, password2]
responses:
200:
$ref: "#/components/responses/userResponse"
@@ -50,7 +72,6 @@ paths:
responses:
200:
$ref: "#/components/responses/gameListResponse"
-
/engine/{uid}:
get:
operationId: gameEngine
@@ -75,27 +96,18 @@ paths:
type: string
format: uuid
requestBody:
- $ref: "#/components/requestBodies/enterCodeRequest"
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ code:
+ type: string
+ required:
+ - code
responses:
200:
$ref: "#/components/responses/taskResponse"
- /file/upload:
- post:
- operationId: uploadFile
- security:
- - cookieAuth: [creator, admin]
- requestBody:
- content:
- multipart/form-data:
- schema:
- type: object
- properties:
- file:
- type: string
- format: binary
- responses:
- 200:
- $ref: "#/components/responses/uploadResponse"
/file/{uid}:
get:
operationId: getFile
@@ -114,24 +126,46 @@ paths:
schema:
type: string
format: binary
+
+ # Admin routes
+ /admin/file/upload:
+ post:
+ operationId: adminUploadFile
+ security:
+ - cookieAuth: [creator, admin]
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ responses:
+ 200:
+ $ref: "#/components/responses/uploadResponse"
/admin/games:
get:
- operationId: listGamesByAdmin
+ operationId: adminListGames
responses:
200:
$ref: "#/components/responses/gameListResponse"
post:
- operationId: createGame
+ operationId: adminEditGame
security:
- cookieAuth: [creator, admin]
requestBody:
- $ref: "#/components/requestBodies/gameEditRequest"
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/gameEdit"
responses:
200:
$ref: "#/components/responses/gameAdminResponse"
/admin/games/{uid}:
get:
- operationId: getGameByAdmin
+ operationId: adminGetGame
parameters:
- name: uid
in: path
@@ -144,22 +178,7 @@ paths:
responses:
200:
$ref: "#/components/responses/gameAdminResponse"
- post:
- operationId: editGame
- parameters:
- - name: uid
- in: path
- required: true
- schema:
- type: string
- format: uuid
- security:
- - cookieAuth: [creator, admin]
- requestBody:
- $ref: "#/components/requestBodies/gameEditRequest"
- responses:
- 200:
- $ref: "#/components/responses/gameAdminResponse"
+
components:
schemas:
userView:
@@ -254,15 +273,10 @@ components:
type: array
items:
$ref: "#/components/schemas/codeView"
- # solutions:
- # type: array
- # items:
- # $ref: '#/components/schemas/solutionView'
required:
- title
- text
- codes
- # - solutions
codeView:
type: object
properties:
@@ -272,15 +286,6 @@ components:
type: string
required:
- description
- solutionView:
- type: object
- properties:
- text:
- type: string
- after:
- type: integer
- required:
- - after
gameEdit:
type: object
properties:
@@ -326,15 +331,10 @@ components:
type: array
items:
$ref: "#/components/schemas/codeEdit"
- # solutions:
- # type: array
- # items:
- # $ref: '#/components/schemas/solutionEdit'
required:
- title
- text
- codes
- # - solutions
codeEdit:
type: object
properties:
@@ -348,78 +348,22 @@ components:
required:
- description
- code
- # solutionEdit:
- # type: object
- # properties:
- # text:
- # type: string
- # after:
- # type: integer
- # required:
- # - after
- # - text
gameType:
type: string
enum:
- virtual
- city
- requestBodies:
- login:
- required: true
- content:
- "application/json":
- schema:
- type: object
- properties:
- email:
- type: string
- password:
- type: string
- required: [email, password]
- register:
- required: true
- content:
- "application/json":
- schema:
- type: object
- properties:
- username:
- type: string
- email:
- type: string
- password:
- type: string
- password2:
- type: string
- required: [username, email, password, password2]
- gameEditRequest:
- required: true
- content:
- "application/json":
- schema:
- $ref: "#/components/schemas/gameEdit"
- enterCodeRequest:
- required: true
- content:
- "application/json":
- schema:
- type: object
- properties:
- code:
- type: string
- required:
- - code
responses:
userResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
$ref: "#/components/schemas/userView"
errorResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
type: object
properties:
@@ -431,7 +375,7 @@ components:
gameListResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
type: array
items:
@@ -439,25 +383,25 @@ components:
gameResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
$ref: "#/components/schemas/gameView"
gameAdminResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
$ref: "#/components/schemas/gameEdit"
taskResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
$ref: "#/components/schemas/taskView"
uploadResponse:
description: ""
content:
- "application/json":
+ application/json:
schema:
type: object
properties:
diff --git a/api/server.go b/api/server.go
index a7b818e..64948a3 100644
--- a/api/server.go
+++ b/api/server.go
@@ -22,17 +22,17 @@ import (
// ServerInterface represents all server handlers.
type ServerInterface interface {
+ // (POST /admin/file/upload)
+ AdminUploadFile(ctx echo.Context) error
+
// (GET /admin/games)
- ListGamesByAdmin(ctx echo.Context) error
+ AdminListGames(ctx echo.Context) error
// (POST /admin/games)
- CreateGame(ctx echo.Context) error
+ AdminEditGame(ctx echo.Context) error
// (GET /admin/games/{uid})
- GetGameByAdmin(ctx echo.Context, uid openapi_types.UUID) error
-
- // (POST /admin/games/{uid})
- EditGame(ctx echo.Context, uid openapi_types.UUID) error
+ AdminGetGame(ctx echo.Context, uid openapi_types.UUID) error
// (GET /engine/{uid})
GameEngine(ctx echo.Context, uid openapi_types.UUID) error
@@ -40,9 +40,6 @@ type ServerInterface interface {
// (POST /engine/{uid}/code)
EnterCode(ctx echo.Context, uid openapi_types.UUID) error
- // (POST /file/upload)
- UploadFile(ctx echo.Context) error
-
// (GET /file/{uid})
GetFile(ctx echo.Context, uid openapi_types.UUID) error
@@ -67,30 +64,41 @@ type ServerInterfaceWrapper struct {
Handler ServerInterface
}
-// ListGamesByAdmin converts echo context to params.
-func (w *ServerInterfaceWrapper) ListGamesByAdmin(ctx echo.Context) error {
+// AdminUploadFile converts echo context to params.
+func (w *ServerInterfaceWrapper) AdminUploadFile(ctx echo.Context) error {
+ var err error
+
+ ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
+
+ // Invoke the callback with all the unmarshaled arguments
+ err = w.Handler.AdminUploadFile(ctx)
+ return err
+}
+
+// AdminListGames converts echo context to params.
+func (w *ServerInterfaceWrapper) AdminListGames(ctx echo.Context) error {
var err error
ctx.Set(CookieAuthScopes, []string{})
// Invoke the callback with all the unmarshaled arguments
- err = w.Handler.ListGamesByAdmin(ctx)
+ err = w.Handler.AdminListGames(ctx)
return err
}
-// CreateGame converts echo context to params.
-func (w *ServerInterfaceWrapper) CreateGame(ctx echo.Context) error {
+// AdminEditGame converts echo context to params.
+func (w *ServerInterfaceWrapper) AdminEditGame(ctx echo.Context) error {
var err error
ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
// Invoke the callback with all the unmarshaled arguments
- err = w.Handler.CreateGame(ctx)
+ err = w.Handler.AdminEditGame(ctx)
return err
}
-// GetGameByAdmin converts echo context to params.
-func (w *ServerInterfaceWrapper) GetGameByAdmin(ctx echo.Context) error {
+// AdminGetGame converts echo context to params.
+func (w *ServerInterfaceWrapper) AdminGetGame(ctx echo.Context) error {
var err error
// ------------- Path parameter "uid" -------------
var uid openapi_types.UUID
@@ -103,25 +111,7 @@ func (w *ServerInterfaceWrapper) GetGameByAdmin(ctx echo.Context) error {
ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
// Invoke the callback with all the unmarshaled arguments
- err = w.Handler.GetGameByAdmin(ctx, uid)
- return err
-}
-
-// EditGame converts echo context to params.
-func (w *ServerInterfaceWrapper) EditGame(ctx echo.Context) error {
- var err error
- // ------------- Path parameter "uid" -------------
- var uid openapi_types.UUID
-
- err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
- }
-
- ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
-
- // Invoke the callback with all the unmarshaled arguments
- err = w.Handler.EditGame(ctx, uid)
+ err = w.Handler.AdminGetGame(ctx, uid)
return err
}
@@ -161,17 +151,6 @@ func (w *ServerInterfaceWrapper) EnterCode(ctx echo.Context) error {
return err
}
-// UploadFile converts echo context to params.
-func (w *ServerInterfaceWrapper) UploadFile(ctx echo.Context) error {
- var err error
-
- ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
-
- // Invoke the callback with all the unmarshaled arguments
- err = w.Handler.UploadFile(ctx)
- return err
-}
-
// GetFile converts echo context to params.
func (w *ServerInterfaceWrapper) GetFile(ctx echo.Context) error {
var err error
@@ -269,13 +248,12 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
Handler: si,
}
- router.GET(baseURL+"/admin/games", wrapper.ListGamesByAdmin)
- router.POST(baseURL+"/admin/games", wrapper.CreateGame)
- router.GET(baseURL+"/admin/games/:uid", wrapper.GetGameByAdmin)
- router.POST(baseURL+"/admin/games/:uid", wrapper.EditGame)
+ router.POST(baseURL+"/admin/file/upload", wrapper.AdminUploadFile)
+ router.GET(baseURL+"/admin/games", wrapper.AdminListGames)
+ router.POST(baseURL+"/admin/games", wrapper.AdminEditGame)
+ router.GET(baseURL+"/admin/games/:uid", wrapper.AdminGetGame)
router.GET(baseURL+"/engine/:uid", wrapper.GameEngine)
router.POST(baseURL+"/engine/:uid/code", wrapper.EnterCode)
- router.POST(baseURL+"/file/upload", wrapper.UploadFile)
router.GET(baseURL+"/file/:uid", wrapper.GetFile)
router.GET(baseURL+"/games", wrapper.GetGames)
router.GET(baseURL+"/user", wrapper.GetUser)
@@ -288,27 +266,26 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "H4sIAAAAAAAC/9RZzW7kNgx+lULt0RvP/px8ywZtUDQo2jTbSzAIFJuZaGNLrkRnMwj87gUl/47lseMa",
- "2fQUR6JF8uNHmuI8s1hluZIg0bDomWn4pwCDn1UiwC6ARNBnKoFLt0NrsZII0j7yPE9FzFEoGX41StKa",
- "ie8h4/SUa5WDxuqoWCVAf3GfA4uYQS3kjpVlYLUKDQmLrp3UNqil1O1XiJGVfTHUBZQB2/EMfk4ELrHt",
- "Jw13LGI/hi0Aods1YX3uiNpU7YT8D0BAxkXqQSJgOTfmm9LJNEzujM4bMyHTsBMGQb+2+e3mB+9uYUBL",
- "ns0gSCMZDEHoapkFiF0xuZKm8k1rpS+rlfW4LiTCDjQ5moExfDc3EVp5vzsJmFiLnGxiEWNVTpwmmZCL",
- "vJifFX7NF8LgIsUCITNzLPhbwDfSVoHBteb7MYuQm4fVYaBDnRF+pUWeKp6swKGiEDaT7pTOOLLILQRT",
- "6UFCc8lCubQ6QHToOEBlUB3T5Inl1NyvxcGBnv0loHXPDMY+QW7DeraWtUfM8OlvMnCgfxKU2G1MwDIT",
- "vYDlSlQdw7DCUYKY2TlN0q6qHOZ0wFBg6ofVLUxXiyuSKwP2KIy47Z11q1QKXA5iUEvW2oMDctjXaycb",
- "ICqEx4J2VZkLssicEo0Fp09XLHDfea31sKl1g1jzAu+Vno9wm49DhGMNHCE5xWWp9sqsOlOFxJHtlahy",
- "wAZn5zEiNARoDezCGjThOkKRJge8dWV+pJtq6on0zBAgPPm5MAbwAWA1VvacoLJ/zOfxWvoyn8fY3em1",
- "6sxTDzdVYyXkI09FUv+r0uZRwhPepPAIlKBEjRvSmwKCN1NfDbImkV/QksNTfqXOCq1B4oV1yZs+Vux3",
- "eJqQAS1AxiOdLSFlVujlZnM1HbdVq7QXdoKuzktFT5xaZG84599ErFWe60gHqNpIXyAGqNcQVuZ7mriA",
- "GYgLLXD/F8FY54t6EHBa4L0Fn9ost0RUto4wA8Z0qlbEeC5+g6pvFvJOWWcdXZn8016mA/YI2ri27f3J",
- "5mRD4KgcJM8Fi9jHk/cnG3vhwntrRmghDRsW7MBmBdHUdpG/JixidD84J4nPe3tJYQf3rw+bzRhxGrlw",
- "cNGwbuTKeBSe2Up87gLUTjf241o6A5DwcMBQLjW3fyPrBpJF1/0QXg9ZWm7pjS7A4XMhknIU5nOwKLcg",
- "51zzDBCobbiuSEKRaynicqx/PQ46Hf9UQ739btCMhZ4CVwX+ldz/X7ML5E5ImCIWmWwF3y6perf+shw4",
- "F9aXtRHa1BPPN8ubwUy2XAumO5FC6AYY4wB9sfu/iNRTUjsDhKxIUeRcY0gYvEs4emYcpLAH062QXO+9",
- "F3bvNO+lXh9MZxbmisVpsgRXEH23NBmZ5qgYAd8Z1MCz/lRnOgqDgY4NYMWe45/+6ptkVvvkk0rb1x3R",
- "+MX1fQt40p2MlQH7tPk4/VJ/etwxMWx+MvCn1B/KWFMvrNiCkuDOL9fxdPNyT3tZtO35rQqc5TjJDez/",
- "NBhuMVPEMRjzQ3X0UotbG7s/iRy38rKWXBChRsvbCdLR2relqmJAP9Z1q9Api1hI3X+5Lf8NAAD//0cV",
- "3sY5HAAA",
+ "H4sIAAAAAAAC/8xY32+kNhD+Vyq3j1zY+/HEWxqlUdWoaq+5vkSryIHJxhewqT3OZRXxv1djAwuLWcge",
+ "Su4pGzx4Zr75vmHsZ5aqolQSJBqWPDMNplTSgPsHtFb6c/2EHqRKIkikn7wsc5FyFErGX42S9Myk91Bw",
+ "+lVqVYJG4fdJVeZex20JLGFCImxAsypiBRjDN91Fg1rIDauqiGn4zwoNGUuu/RY7+3XU2Kvbr5Aiq+iF",
+ "DEyqRUkxsYTR/htewGlWCHlUFr9ouGMJ+zneYRT7VRPTzueZOOj5Uhg8yrFAKMycCP4V8I281WBwrfl2",
+ "LCLk5mFxGGhTH0TYqS1zxbMFOGStyOjvndIFR5b4B9EEbZzRXLJYA3pxgGjTcYCqqN6m1Ynj1JSCmmz3",
+ "NgysHwNad8/Iux5C6BdcZktFeyCMkP9WgQP/k6CkfmEClpnoRaxUom6fww5HAjGzNU3WvqvsazpiKDAP",
+ "w+ofTHeLK7KrIvYojLjt7XWrVA5cDmrQWDbeoz1yuNebJFsgaoTHinZVhwvSFt6JRstz4prAbee1XYZt",
+ "rxvUmlu8V3o+wjs9DhFONXCE7BSPk9ors+pMWYkjywtRZY8NPs5DRGgJsAuwC2vUlusARVoNBPvK/Eq3",
+ "3TRQ6ZklQHgKc2EM4D3AGqzcPlEd/1jO4730ZTmPsbszazXKUw839WAl5CPPRdb8q/L2p4QnvMnhEUig",
+ "RI0b8psDQlCprwZZK+QBZFBwkQdjgKfySp1ZrUHipUspKB9n9ic8TdiAFiDTkcmWkDILzHKzuZqPx6pV",
+ "3is7QdfoUtEvTiNysJxkKnkxo3AuqtY8qqvQA6oJMlSIAeoNhHX4gSEuYgZSqwVu/yEYG72oBwGnFu8d",
+ "+DRm+UdEZZcIM2BMp2sljJfiD6jnZiHvlEvW05XJvy0YYuIjaOPHtvcnq5MVgaNKkLwULGEfT96frKj/",
+ "cbx3YcQO0vhO5BD7GdjxVBknDmKrGyZ/z1jC3AHlizP6TTjyE65g8FeVbfcG0cLmKEquMSZCvMs4BmZl",
+ "8trjzK2QXG+Dg19gMu6dAT+sVmPkbe3ivSm/WxqWXPeLcj3kXbWmN2rIWuFsYAwrOlddNOR4cbCDk5lL",
+ "+kBp6CNy4Uk9XphlTpLVsQn1D7nfX4D42YqsOlyGC2hgKbnmBSDQHHZdq46ksNOcb1q7foHaQtQBaOqE",
+ "sn5TYEBuhIQJTAiLc2f44yLSuwPwfOslFzdHt7AcziWCPvNzwStleJzeZp1HQ1dMobuCaimk3ddggkSA",
+ "9TfgzRg0ArJKEfCdQQ286IM9/ZkZ3Hy4L1SNyuGGXzeZ5Vo9uXQD0AGPX/yAdMSHsHuFVEXs0+rj9Ev9",
+ "a9ZOiHGuNkKOy/EvZVyol85sKbWMj88lN+ab0tm0lprhr31jMV0NEV69HOHeR2Ddw1tZnAU42Q3i/zS4",
+ "fWLGpikY81O99bER72LUsBEGPX8PR/m5sXxTZuwWPwRX558wAoeL1m/Xy4/NtYMTyJqasgH92LR9q3OW",
+ "sJhOGdW6+j8AAP//fdZwRK4ZAAA=",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/api/types.go b/api/types.go
index 901ffec..03ef2b4 100644
--- a/api/types.go
+++ b/api/types.go
@@ -132,36 +132,14 @@ type UploadResponse struct {
// UserResponse defines model for userResponse.
type UserResponse = UserView
-// EnterCodeRequest defines model for enterCodeRequest.
-type EnterCodeRequest struct {
- Code string `json:"code"`
-}
-
-// GameEditRequest defines model for gameEditRequest.
-type GameEditRequest = GameEdit
-
-// Login defines model for login.
-type Login struct {
- Email string `json:"email"`
- Password string `json:"password"`
-}
-
-// Register defines model for register.
-type Register struct {
- Email string `json:"email"`
- Password string `json:"password"`
- Password2 string `json:"password2"`
- Username string `json:"username"`
-}
+// AdminUploadFileMultipartBody defines parameters for AdminUploadFile.
+type AdminUploadFileMultipartBody interface{}
// EnterCodeJSONBody defines parameters for EnterCode.
type EnterCodeJSONBody struct {
Code string `json:"code"`
}
-// UploadFileMultipartBody defines parameters for UploadFile.
-type UploadFileMultipartBody interface{}
-
// PostUserLoginJSONBody defines parameters for PostUserLogin.
type PostUserLoginJSONBody struct {
Email string `json:"email"`
@@ -176,18 +154,15 @@ type PostUserRegisterJSONBody struct {
Username string `json:"username"`
}
-// CreateGameJSONRequestBody defines body for CreateGame for application/json ContentType.
-type CreateGameJSONRequestBody = GameEdit
+// AdminUploadFileMultipartRequestBody defines body for AdminUploadFile for multipart/form-data ContentType.
+type AdminUploadFileMultipartRequestBody AdminUploadFileMultipartBody
-// EditGameJSONRequestBody defines body for EditGame for application/json ContentType.
-type EditGameJSONRequestBody = GameEdit
+// AdminEditGameJSONRequestBody defines body for AdminEditGame for application/json ContentType.
+type AdminEditGameJSONRequestBody = GameEdit
// EnterCodeJSONRequestBody defines body for EnterCode for application/json ContentType.
type EnterCodeJSONRequestBody EnterCodeJSONBody
-// UploadFileMultipartRequestBody defines body for UploadFile for multipart/form-data ContentType.
-type UploadFileMultipartRequestBody UploadFileMultipartBody
-
// PostUserLoginJSONRequestBody defines body for PostUserLogin for application/json ContentType.
type PostUserLoginJSONRequestBody PostUserLoginJSONBody
diff --git a/auth.go b/auth.go
new file mode 100644
index 0000000..5492b2a
--- /dev/null
+++ b/auth.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+ "context"
+
+ "github.com/getkin/kin-openapi/openapi3filter"
+ "github.com/labstack/echo/v4"
+ oapiMiddleware "github.com/oapi-codegen/echo-middleware"
+ appmiddleware "gitrepo.ru/neonxp/nquest/pkg/contextlib"
+
+ "gitrepo.ru/neonxp/nquest/pkg/models"
+)
+
+var authFunc = func(ctx context.Context, ai *openapi3filter.AuthenticationInput) error {
+ echoCtx := ctx.Value(oapiMiddleware.EchoContextKey).(echo.Context)
+ user := appmiddleware.GetUser(echoCtx)
+ if user != nil {
+ if len(ai.Scopes) > 0 {
+ for _, v := range ai.Scopes {
+ switch v {
+ case "user":
+ return nil
+ case "creator":
+ if user.HasRole(models.RoleCreator) {
+ return nil
+ }
+ case "admin":
+ if user.HasRole(models.RoleAdmin) {
+ return nil
+ }
+ }
+ }
+
+ return echo.ErrForbidden
+ }
+
+ return nil
+ }
+
+ return echo.ErrForbidden
+}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index adf8c12..5f3bf13 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -77,9 +77,8 @@ function Auth (props) {
if (!user && !baseUser) {
return