Фикс ошибок
This commit is contained in:
parent
7e706a3981
commit
a1dc96088c
34 changed files with 1584 additions and 1180 deletions
|
@ -1,4 +1,5 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
|
//go:generate merger -i parts/common.yaml -i parts/game.yaml -i parts/admin.yaml -i parts/user.yaml -i parts/schemas.yaml -i parts/responses.yaml -o openapi.yaml
|
||||||
//go:generate oapi-codegen -generate server,spec -package api -o ./server.go ./openapi.yaml
|
//go:generate oapi-codegen -generate server,spec -package api -o ./server.go ./openapi.yaml
|
||||||
//go:generate oapi-codegen -generate types -package api -o ./types.go ./openapi.yaml
|
//go:generate oapi-codegen -generate types -package api -o ./types.go ./openapi.yaml
|
||||||
|
|
774
api/openapi.yaml
774
api/openapi.yaml
|
@ -1,237 +1,245 @@
|
||||||
openapi: "3.1.0"
|
components:
|
||||||
|
|
||||||
info:
|
|
||||||
version: 1.0.0
|
|
||||||
title: nQuest
|
|
||||||
|
|
||||||
servers:
|
|
||||||
- url: /api
|
|
||||||
|
|
||||||
paths:
|
|
||||||
# User routes
|
|
||||||
/user:
|
|
||||||
get:
|
|
||||||
responses:
|
responses:
|
||||||
200:
|
errorResponse:
|
||||||
$ref: "#/components/responses/userResponse"
|
|
||||||
403:
|
|
||||||
$ref: "#/components/responses/errorResponse"
|
|
||||||
/user/login:
|
|
||||||
post:
|
|
||||||
security: []
|
|
||||||
requestBody:
|
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
email:
|
|
||||||
type: string
|
|
||||||
password:
|
|
||||||
type: string
|
|
||||||
required: [email, password]
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/userResponse"
|
|
||||||
400:
|
|
||||||
$ref: "#/components/responses/errorResponse"
|
|
||||||
/user/register:
|
|
||||||
post:
|
|
||||||
security: []
|
|
||||||
requestBody:
|
|
||||||
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"
|
|
||||||
400:
|
|
||||||
$ref: "#/components/responses/errorResponse"
|
|
||||||
/user/logout:
|
|
||||||
post:
|
|
||||||
responses:
|
|
||||||
204:
|
|
||||||
description: "success logout"
|
|
||||||
400:
|
|
||||||
$ref: "#/components/responses/errorResponse"
|
|
||||||
|
|
||||||
# Game routes
|
|
||||||
/games:
|
|
||||||
get:
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/gameListResponse"
|
|
||||||
/engine/{uid}:
|
|
||||||
get:
|
|
||||||
operationId: gameEngine
|
|
||||||
parameters:
|
|
||||||
- name: uid
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/taskResponse"
|
|
||||||
/engine/{uid}/code:
|
|
||||||
post:
|
|
||||||
operationId: enterCode
|
|
||||||
parameters:
|
|
||||||
- name: uid
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
properties:
|
||||||
code:
|
code:
|
||||||
|
type: integer
|
||||||
|
message:
|
||||||
type: string
|
type: string
|
||||||
required:
|
required:
|
||||||
- code
|
- code
|
||||||
responses:
|
- message
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/taskResponse"
|
|
||||||
/file/{uid}:
|
|
||||||
get:
|
|
||||||
operationId: getFile
|
|
||||||
parameters:
|
|
||||||
- name: uid
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: file
|
|
||||||
content:
|
|
||||||
"application/octet-stream":
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: binary
|
|
||||||
|
|
||||||
# Admin routes
|
|
||||||
/admin/file/{quest}/upload:
|
|
||||||
post:
|
|
||||||
operationId: adminUploadFile
|
|
||||||
security:
|
|
||||||
- cookieAuth: [creator, admin]
|
|
||||||
parameters:
|
|
||||||
- name: quest
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
multipart/form-data:
|
|
||||||
schema:
|
|
||||||
type: object
|
type: object
|
||||||
properties:
|
description: ""
|
||||||
file:
|
filesListResponse:
|
||||||
type: string
|
|
||||||
format: binary
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/uploadResponse"
|
|
||||||
/admin/file/{quest}:
|
|
||||||
get:
|
|
||||||
operationId: adminListFiles
|
|
||||||
security:
|
|
||||||
- cookieAuth: [creator, admin]
|
|
||||||
parameters:
|
|
||||||
- name: quest
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/filesListResponse"
|
|
||||||
|
|
||||||
/admin/games:
|
|
||||||
get:
|
|
||||||
operationId: adminListGames
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/gameListResponse"
|
|
||||||
post:
|
|
||||||
operationId: adminEditGame
|
|
||||||
security:
|
|
||||||
- cookieAuth: [creator, admin]
|
|
||||||
requestBody:
|
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/gameEdit"
|
items:
|
||||||
responses:
|
$ref: '#/components/schemas/fileItem'
|
||||||
200:
|
type: array
|
||||||
$ref: "#/components/responses/gameAdminResponse"
|
description: ""
|
||||||
/admin/games/{uid}:
|
gameAdminResponse:
|
||||||
get:
|
content:
|
||||||
operationId: adminGetGame
|
application/json:
|
||||||
parameters:
|
|
||||||
- name: uid
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
schema:
|
||||||
type: string
|
$ref: '#/components/schemas/gameEdit'
|
||||||
|
description: ""
|
||||||
|
gameListResponse:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/gameView'
|
||||||
|
type: array
|
||||||
|
description: ""
|
||||||
|
gameResponse:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/gameView'
|
||||||
|
description: ""
|
||||||
|
taskResponse:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/taskView'
|
||||||
|
description: ""
|
||||||
|
uploadResponse:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
uuid:
|
||||||
format: uuid
|
format: uuid
|
||||||
security:
|
type: string
|
||||||
- cookieAuth: [creator, admin]
|
required:
|
||||||
responses:
|
- uuid
|
||||||
200:
|
|
||||||
$ref: "#/components/responses/gameAdminResponse"
|
|
||||||
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
userView:
|
|
||||||
type: object
|
type: object
|
||||||
|
description: ""
|
||||||
|
userResponse:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/userView'
|
||||||
|
description: ""
|
||||||
|
schemas:
|
||||||
|
codeEdit:
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
type: object
|
||||||
|
codeView:
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
fileItem:
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: string
|
|
||||||
format: uuid
|
format: uuid
|
||||||
username:
|
|
||||||
type: string
|
type: string
|
||||||
|
originalName:
|
||||||
|
type: string
|
||||||
|
size:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- originalName
|
||||||
|
- size
|
||||||
|
type: object
|
||||||
|
gameEdit:
|
||||||
|
properties:
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
icon:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
points:
|
||||||
|
type: integer
|
||||||
|
tasks:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/taskEdit'
|
||||||
|
type: array
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
$ref: '#/components/schemas/gameType'
|
||||||
|
visible:
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- visible
|
||||||
|
- title
|
||||||
|
- description
|
||||||
|
- type
|
||||||
|
- tasks
|
||||||
|
- points
|
||||||
|
type: object
|
||||||
|
gameType:
|
||||||
|
enum:
|
||||||
|
- virtual
|
||||||
|
- city
|
||||||
|
type: string
|
||||||
|
gameView:
|
||||||
|
properties:
|
||||||
|
authors:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/userView'
|
||||||
|
type: array
|
||||||
|
createdAt:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
icon:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
points:
|
||||||
|
type: integer
|
||||||
|
taskCount:
|
||||||
|
type: integer
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
$ref: '#/components/schemas/gameType'
|
||||||
|
visible:
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- title
|
||||||
|
- description
|
||||||
|
- type
|
||||||
|
- points
|
||||||
|
- taskCount
|
||||||
|
- createdAt
|
||||||
|
- authors
|
||||||
|
type: object
|
||||||
|
taskEdit:
|
||||||
|
properties:
|
||||||
|
codes:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/codeEdit'
|
||||||
|
type: array
|
||||||
|
id:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
text:
|
||||||
|
type: string
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- title
|
||||||
|
- text
|
||||||
|
- codes
|
||||||
|
type: object
|
||||||
|
taskView:
|
||||||
|
properties:
|
||||||
|
codes:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/codeView'
|
||||||
|
type: array
|
||||||
|
message:
|
||||||
|
enum:
|
||||||
|
- ok_code
|
||||||
|
- invalid_code
|
||||||
|
- old_code
|
||||||
|
- next_level
|
||||||
|
- game_complete
|
||||||
|
type: string
|
||||||
|
text:
|
||||||
|
type: string
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- title
|
||||||
|
- text
|
||||||
|
- codes
|
||||||
|
type: object
|
||||||
|
userView:
|
||||||
|
properties:
|
||||||
email:
|
email:
|
||||||
type: string
|
type: string
|
||||||
experience:
|
|
||||||
type: integer
|
|
||||||
level:
|
|
||||||
type: integer
|
|
||||||
expToCurrentLevel:
|
expToCurrentLevel:
|
||||||
type: integer
|
type: integer
|
||||||
expToNextLevel:
|
expToNextLevel:
|
||||||
type: integer
|
type: integer
|
||||||
|
experience:
|
||||||
|
type: integer
|
||||||
games:
|
games:
|
||||||
type: array
|
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/gameView"
|
$ref: '#/components/schemas/gameView'
|
||||||
role:
|
type: array
|
||||||
|
id:
|
||||||
|
format: uuid
|
||||||
type: string
|
type: string
|
||||||
|
level:
|
||||||
|
type: integer
|
||||||
|
role:
|
||||||
enum:
|
enum:
|
||||||
- user
|
- user
|
||||||
- creator
|
- creator
|
||||||
- admin
|
- admin
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
required:
|
required:
|
||||||
- id
|
- id
|
||||||
- username
|
- username
|
||||||
|
@ -242,221 +250,201 @@ components:
|
||||||
- expToNextLevel
|
- expToNextLevel
|
||||||
- games
|
- games
|
||||||
- role
|
- role
|
||||||
gameView:
|
|
||||||
type: object
|
type: object
|
||||||
|
securitySchemes:
|
||||||
|
cookieAuth:
|
||||||
|
in: cookie
|
||||||
|
name: session
|
||||||
|
type: apiKey
|
||||||
|
info:
|
||||||
|
title: nQuest
|
||||||
|
version: 1.0.0
|
||||||
|
openapi: 3.1.0
|
||||||
|
paths:
|
||||||
|
/admin/file/{quest}:
|
||||||
|
get:
|
||||||
|
operationId: adminListFiles
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: quest
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: '#/components/responses/filesListResponse'
|
||||||
|
security:
|
||||||
|
- cookieAuth:
|
||||||
|
- creator
|
||||||
|
- admin
|
||||||
|
/admin/file/{quest}/upload:
|
||||||
|
post:
|
||||||
|
operationId: adminUploadFile
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: quest
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
properties:
|
properties:
|
||||||
id:
|
file:
|
||||||
|
format: binary
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
schema: null
|
||||||
visible:
|
|
||||||
type: boolean
|
|
||||||
title:
|
|
||||||
type: string
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
$ref: "#/components/schemas/gameType"
|
|
||||||
points:
|
|
||||||
type: integer
|
|
||||||
taskCount:
|
|
||||||
type: integer
|
|
||||||
createdAt:
|
|
||||||
type: string
|
|
||||||
authors:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/userView"
|
|
||||||
icon:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
required:
|
|
||||||
- id
|
|
||||||
- title
|
|
||||||
- description
|
|
||||||
- type
|
|
||||||
- points
|
|
||||||
- taskCount
|
|
||||||
- createdAt
|
|
||||||
- authors
|
|
||||||
taskView:
|
|
||||||
type: object
|
type: object
|
||||||
properties:
|
responses:
|
||||||
message:
|
200:
|
||||||
type: string
|
$ref: '#/components/responses/uploadResponse'
|
||||||
enum:
|
security:
|
||||||
- ok_code
|
- cookieAuth:
|
||||||
- invalid_code
|
- creator
|
||||||
- old_code
|
- admin
|
||||||
- next_level
|
/admin/games:
|
||||||
- game_complete
|
get:
|
||||||
title:
|
operationId: adminListGames
|
||||||
type: string
|
responses:
|
||||||
text:
|
200:
|
||||||
type: string
|
$ref: '#/components/responses/gameListResponse'
|
||||||
codes:
|
post:
|
||||||
type: array
|
operationId: adminEditGame
|
||||||
items:
|
requestBody:
|
||||||
$ref: "#/components/schemas/codeView"
|
content:
|
||||||
required:
|
application/json:
|
||||||
- title
|
schema:
|
||||||
- text
|
$ref: '#/components/schemas/gameEdit'
|
||||||
- codes
|
responses:
|
||||||
codeView:
|
200:
|
||||||
type: object
|
$ref: '#/components/responses/gameAdminResponse'
|
||||||
properties:
|
security:
|
||||||
description:
|
- cookieAuth:
|
||||||
type: string
|
- creator
|
||||||
code:
|
- admin
|
||||||
type: string
|
/admin/games/{uid}:
|
||||||
gameEdit:
|
get:
|
||||||
type: object
|
operationId: adminGetGame
|
||||||
properties:
|
parameters:
|
||||||
id:
|
- in: path
|
||||||
type: string
|
name: uid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
format: uuid
|
format: uuid
|
||||||
visible:
|
|
||||||
type: boolean
|
|
||||||
title:
|
|
||||||
type: string
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
$ref: "#/components/schemas/gameType"
|
|
||||||
tasks:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/taskEdit"
|
|
||||||
points:
|
|
||||||
type: integer
|
|
||||||
icon:
|
|
||||||
type: string
|
type: string
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: '#/components/responses/gameAdminResponse'
|
||||||
|
security:
|
||||||
|
- cookieAuth:
|
||||||
|
- creator
|
||||||
|
- admin
|
||||||
|
/engine/{uid}:
|
||||||
|
get:
|
||||||
|
operationId: gameEngine
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: uid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
format: uuid
|
format: uuid
|
||||||
required:
|
type: string
|
||||||
- visible
|
responses:
|
||||||
- title
|
200:
|
||||||
- description
|
$ref: '#/components/responses/taskResponse'
|
||||||
- type
|
/engine/{uid}/code:
|
||||||
- tasks
|
post:
|
||||||
- points
|
operationId: enterCode
|
||||||
taskEdit:
|
parameters:
|
||||||
type: object
|
- in: path
|
||||||
|
name: uid
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
properties:
|
properties:
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
title:
|
|
||||||
type: string
|
|
||||||
text:
|
|
||||||
type: string
|
|
||||||
codes:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/codeEdit"
|
|
||||||
required:
|
|
||||||
- title
|
|
||||||
- text
|
|
||||||
- codes
|
|
||||||
codeEdit:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
code:
|
code:
|
||||||
type: string
|
type: string
|
||||||
required:
|
required:
|
||||||
- code
|
- code
|
||||||
gameType:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- virtual
|
|
||||||
- city
|
|
||||||
fileItem:
|
|
||||||
type: object
|
type: object
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
originalName:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
required:
|
|
||||||
- id
|
|
||||||
- originalName
|
|
||||||
- size
|
|
||||||
responses:
|
responses:
|
||||||
userResponse:
|
200:
|
||||||
description: ""
|
$ref: '#/components/responses/taskResponse'
|
||||||
|
/games:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: '#/components/responses/gameListResponse'
|
||||||
|
/user:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: '#/components/responses/userResponse'
|
||||||
|
403:
|
||||||
|
$ref: '#/components/responses/errorResponse'
|
||||||
|
/user/login:
|
||||||
|
post:
|
||||||
|
requestBody:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/userView"
|
|
||||||
errorResponse:
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
properties:
|
||||||
code:
|
email:
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
type: string
|
type: string
|
||||||
required: [code, message]
|
password:
|
||||||
gameListResponse:
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/gameView"
|
|
||||||
gameResponse:
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/gameView"
|
|
||||||
gameAdminResponse:
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/gameEdit"
|
|
||||||
taskResponse:
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/taskView"
|
|
||||||
uploadResponse:
|
|
||||||
description: ""
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
uuid:
|
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
|
||||||
required:
|
required:
|
||||||
- uuid
|
- email
|
||||||
filesListResponse:
|
- password
|
||||||
description: ""
|
type: object
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: '#/components/responses/userResponse'
|
||||||
|
400:
|
||||||
|
$ref: '#/components/responses/errorResponse'
|
||||||
|
security: []
|
||||||
|
/user/logout:
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
204:
|
||||||
|
description: success logout
|
||||||
|
400:
|
||||||
|
$ref: '#/components/responses/errorResponse'
|
||||||
|
/user/register:
|
||||||
|
post:
|
||||||
|
requestBody:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
properties:
|
||||||
items:
|
email:
|
||||||
$ref: "#/components/schemas/fileItem"
|
type: string
|
||||||
securitySchemes:
|
password:
|
||||||
cookieAuth:
|
type: string
|
||||||
type: apiKey
|
password2:
|
||||||
in: cookie
|
type: string
|
||||||
name: session
|
username:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- username
|
||||||
|
- email
|
||||||
|
- password
|
||||||
|
- password2
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: '#/components/responses/userResponse'
|
||||||
|
400:
|
||||||
|
$ref: '#/components/responses/errorResponse'
|
||||||
|
security: []
|
||||||
security:
|
security:
|
||||||
- cookieAuth: []
|
- cookieAuth: []
|
||||||
|
servers:
|
||||||
|
- url: /api
|
||||||
|
|
74
api/parts/admin.yaml
Normal file
74
api/parts/admin.yaml
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
paths:
|
||||||
|
/admin/file/{quest}/upload:
|
||||||
|
post:
|
||||||
|
operationId: adminUploadFile
|
||||||
|
security:
|
||||||
|
- cookieAuth: [creator, admin]
|
||||||
|
parameters:
|
||||||
|
- name: quest
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
file:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/uploadResponse"
|
||||||
|
/admin/file/{quest}:
|
||||||
|
get:
|
||||||
|
operationId: adminListFiles
|
||||||
|
security:
|
||||||
|
- cookieAuth: [creator, admin]
|
||||||
|
parameters:
|
||||||
|
- name: quest
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/filesListResponse"
|
||||||
|
|
||||||
|
/admin/games:
|
||||||
|
get:
|
||||||
|
operationId: adminListGames
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/gameListResponse"
|
||||||
|
post:
|
||||||
|
operationId: adminEditGame
|
||||||
|
security:
|
||||||
|
- cookieAuth: [creator, admin]
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/gameEdit"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/gameAdminResponse"
|
||||||
|
/admin/games/{uid}:
|
||||||
|
get:
|
||||||
|
operationId: adminGetGame
|
||||||
|
parameters:
|
||||||
|
- name: uid
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
security:
|
||||||
|
- cookieAuth: [creator, admin]
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/gameAdminResponse"
|
19
api/parts/common.yaml
Normal file
19
api/parts/common.yaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
openapi: "3.1.0"
|
||||||
|
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: nQuest
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: /api
|
||||||
|
|
||||||
|
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
cookieAuth:
|
||||||
|
type: apiKey
|
||||||
|
in: cookie
|
||||||
|
name: session
|
||||||
|
|
||||||
|
security:
|
||||||
|
- cookieAuth: []
|
43
api/parts/game.yaml
Normal file
43
api/parts/game.yaml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
paths:
|
||||||
|
/games:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/gameListResponse"
|
||||||
|
/engine/{uid}:
|
||||||
|
get:
|
||||||
|
operationId: gameEngine
|
||||||
|
parameters:
|
||||||
|
- name: uid
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/taskResponse"
|
||||||
|
/engine/{uid}/code:
|
||||||
|
post:
|
||||||
|
operationId: enterCode
|
||||||
|
parameters:
|
||||||
|
- name: uid
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/taskResponse"
|
||||||
|
|
66
api/parts/responses.yaml
Normal file
66
api/parts/responses.yaml
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
components:
|
||||||
|
responses:
|
||||||
|
userResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/userView"
|
||||||
|
errorResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
required: [code, message]
|
||||||
|
gameListResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/gameView"
|
||||||
|
gameResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/gameView"
|
||||||
|
gameAdminResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/gameEdit"
|
||||||
|
taskResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/taskView"
|
||||||
|
uploadResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
uuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
required:
|
||||||
|
- uuid
|
||||||
|
filesListResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/fileItem"
|
186
api/parts/schemas.yaml
Normal file
186
api/parts/schemas.yaml
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
userView:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
experience:
|
||||||
|
type: integer
|
||||||
|
level:
|
||||||
|
type: integer
|
||||||
|
expToCurrentLevel:
|
||||||
|
type: integer
|
||||||
|
expToNextLevel:
|
||||||
|
type: integer
|
||||||
|
games:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/gameView"
|
||||||
|
role:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- user
|
||||||
|
- creator
|
||||||
|
- admin
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- username
|
||||||
|
- email
|
||||||
|
- experience
|
||||||
|
- level
|
||||||
|
- expToCurrentLevel
|
||||||
|
- expToNextLevel
|
||||||
|
- games
|
||||||
|
- role
|
||||||
|
gameView:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
visible:
|
||||||
|
type: boolean
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
$ref: "#/components/schemas/gameType"
|
||||||
|
points:
|
||||||
|
type: integer
|
||||||
|
taskCount:
|
||||||
|
type: integer
|
||||||
|
createdAt:
|
||||||
|
type: string
|
||||||
|
authors:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/userView"
|
||||||
|
icon:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- title
|
||||||
|
- description
|
||||||
|
- type
|
||||||
|
- points
|
||||||
|
- taskCount
|
||||||
|
- createdAt
|
||||||
|
- authors
|
||||||
|
taskView:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- ok_code
|
||||||
|
- invalid_code
|
||||||
|
- old_code
|
||||||
|
- next_level
|
||||||
|
- game_complete
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
text:
|
||||||
|
type: string
|
||||||
|
codes:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/codeView"
|
||||||
|
required:
|
||||||
|
- title
|
||||||
|
- text
|
||||||
|
- codes
|
||||||
|
codeView:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
gameEdit:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
visible:
|
||||||
|
type: boolean
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
$ref: "#/components/schemas/gameType"
|
||||||
|
tasks:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/taskEdit"
|
||||||
|
points:
|
||||||
|
type: integer
|
||||||
|
icon:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
required:
|
||||||
|
- visible
|
||||||
|
- title
|
||||||
|
- description
|
||||||
|
- type
|
||||||
|
- tasks
|
||||||
|
- points
|
||||||
|
taskEdit:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
text:
|
||||||
|
type: string
|
||||||
|
codes:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/codeEdit"
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- title
|
||||||
|
- text
|
||||||
|
- codes
|
||||||
|
codeEdit:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
gameType:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- virtual
|
||||||
|
- city
|
||||||
|
fileItem:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
originalName:
|
||||||
|
type: string
|
||||||
|
size:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- originalName
|
||||||
|
- size
|
57
api/parts/user.yaml
Normal file
57
api/parts/user.yaml
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
paths:
|
||||||
|
/user:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/userResponse"
|
||||||
|
403:
|
||||||
|
$ref: "#/components/responses/errorResponse"
|
||||||
|
/user/login:
|
||||||
|
post:
|
||||||
|
security: []
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
required: [email, password]
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/userResponse"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/errorResponse"
|
||||||
|
/user/register:
|
||||||
|
post:
|
||||||
|
security: []
|
||||||
|
requestBody:
|
||||||
|
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"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/errorResponse"
|
||||||
|
/user/logout:
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
204:
|
||||||
|
description: "success logout"
|
||||||
|
400:
|
||||||
|
$ref: "#/components/responses/errorResponse"
|
|
@ -43,9 +43,6 @@ type ServerInterface interface {
|
||||||
// (POST /engine/{uid}/code)
|
// (POST /engine/{uid}/code)
|
||||||
EnterCode(ctx echo.Context, uid openapi_types.UUID) error
|
EnterCode(ctx echo.Context, uid openapi_types.UUID) error
|
||||||
|
|
||||||
// (GET /file/{uid})
|
|
||||||
GetFile(ctx echo.Context, uid openapi_types.UUID) error
|
|
||||||
|
|
||||||
// (GET /games)
|
// (GET /games)
|
||||||
GetGames(ctx echo.Context) error
|
GetGames(ctx echo.Context) error
|
||||||
|
|
||||||
|
@ -179,24 +176,6 @@ func (w *ServerInterfaceWrapper) EnterCode(ctx echo.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFile converts echo context to params.
|
|
||||||
func (w *ServerInterfaceWrapper) GetFile(ctx echo.Context) error {
|
|
||||||
var err error
|
|
||||||
// ------------- Path parameter "uid" -------------
|
|
||||||
var uid openapi_types.UUID
|
|
||||||
|
|
||||||
err = runtime.BindStyledParameterWithOptions("simple", "uid", ctx.Param("uid"), &uid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
|
||||||
if err != nil {
|
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Set(CookieAuthScopes, []string{})
|
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshaled arguments
|
|
||||||
err = w.Handler.GetFile(ctx, uid)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetGames converts echo context to params.
|
// GetGames converts echo context to params.
|
||||||
func (w *ServerInterfaceWrapper) GetGames(ctx echo.Context) error {
|
func (w *ServerInterfaceWrapper) GetGames(ctx echo.Context) error {
|
||||||
var err error
|
var err error
|
||||||
|
@ -283,7 +262,6 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
||||||
router.GET(baseURL+"/admin/games/:uid", wrapper.AdminGetGame)
|
router.GET(baseURL+"/admin/games/:uid", wrapper.AdminGetGame)
|
||||||
router.GET(baseURL+"/engine/:uid", wrapper.GameEngine)
|
router.GET(baseURL+"/engine/:uid", wrapper.GameEngine)
|
||||||
router.POST(baseURL+"/engine/:uid/code", wrapper.EnterCode)
|
router.POST(baseURL+"/engine/:uid/code", wrapper.EnterCode)
|
||||||
router.GET(baseURL+"/file/:uid", wrapper.GetFile)
|
|
||||||
router.GET(baseURL+"/games", wrapper.GetGames)
|
router.GET(baseURL+"/games", wrapper.GetGames)
|
||||||
router.GET(baseURL+"/user", wrapper.GetUser)
|
router.GET(baseURL+"/user", wrapper.GetUser)
|
||||||
router.POST(baseURL+"/user/login", wrapper.PostUserLogin)
|
router.POST(baseURL+"/user/login", wrapper.PostUserLogin)
|
||||||
|
@ -295,27 +273,26 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"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",
|
||||||
"DejHuuwXOmURC2nkK9fl/wEAAP//MtUIV2ocAAA=",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
|
|
@ -85,7 +85,7 @@ type GameView struct {
|
||||||
// TaskEdit defines model for taskEdit.
|
// TaskEdit defines model for taskEdit.
|
||||||
type TaskEdit struct {
|
type TaskEdit struct {
|
||||||
Codes []CodeEdit `json:"codes"`
|
Codes []CodeEdit `json:"codes"`
|
||||||
Id *openapi_types.UUID `json:"id,omitempty"`
|
Id openapi_types.UUID `json:"id"`
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,6 @@ module.exports = {
|
||||||
'react'
|
'react'
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
|
indent: ['error', 4]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ const Quest = () => {
|
||||||
{tasks.map(renderTaskForm(remove))}
|
{tasks.map(renderTaskForm(remove))}
|
||||||
<Form.Item wrapperCol={buttonLayout}>
|
<Form.Item wrapperCol={buttonLayout}>
|
||||||
<Button type='primary' onClick={() => add()} block>
|
<Button type='primary' onClick={() => add()} block>
|
||||||
<PlusOutlined/> Добавить уровень
|
<PlusOutlined /> Добавить уровень
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
|
@ -132,12 +132,12 @@ const Quest = () => {
|
||||||
action={`/api/admin/file/${quest.id}/upload`}
|
action={`/api/admin/file/${quest.id}/upload`}
|
||||||
listType='picture'
|
listType='picture'
|
||||||
maxCount={10}
|
maxCount={10}
|
||||||
itemRender={renderFile}
|
itemRender={(e, file) => renderFile(e, file, quest)}
|
||||||
>
|
>
|
||||||
<Button icon={<UploadOutlined />}>Загрузка</Button>
|
<Button icon={<UploadOutlined />}>Загрузка</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
Ранее загруженные файлы:
|
Ранее загруженные файлы:
|
||||||
<List dataSource={files} renderItem={renderFileItem} />
|
<List dataSource={files} renderItem={x => renderFileItem(x, quest)} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -165,8 +165,7 @@ const Quest = () => {
|
||||||
</List.Item>
|
</List.Item>
|
||||||
)} />
|
)} />
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
|
@ -184,7 +183,7 @@ const renderTaskForm = remove => task => (
|
||||||
cancelText='Нет'
|
cancelText='Нет'
|
||||||
>
|
>
|
||||||
<Button danger>
|
<Button danger>
|
||||||
<CloseOutlined/> Удалить уровень
|
<CloseOutlined /> Удалить уровень
|
||||||
</Button>
|
</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
]}
|
]}
|
||||||
|
@ -204,7 +203,7 @@ const renderTaskForm = remove => task => (
|
||||||
{codes.map(renderCodeForm(codesOpts.remove))}
|
{codes.map(renderCodeForm(codesOpts.remove))}
|
||||||
<Form.Item wrapperCol={{ offset: 6, span: 14 }}>
|
<Form.Item wrapperCol={{ offset: 6, span: 14 }}>
|
||||||
<Button key='addCode' type='primary' onClick={() => codesOpts.add()} block>
|
<Button key='addCode' type='primary' onClick={() => codesOpts.add()} block>
|
||||||
<PlusOutlined/> Добавить код
|
<PlusOutlined /> Добавить код
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
|
@ -227,7 +226,7 @@ const renderCodeForm = remove => code => (
|
||||||
// cancelText='Нет'
|
// cancelText='Нет'
|
||||||
// >
|
// >
|
||||||
<Button key="delete" danger onClick={() => remove(code.name)}>
|
<Button key="delete" danger onClick={() => remove(code.name)}>
|
||||||
<CloseOutlined/> Удалить код
|
<CloseOutlined /> Удалить код
|
||||||
</Button>
|
</Button>
|
||||||
// </Popconfirm>
|
// </Popconfirm>
|
||||||
]}
|
]}
|
||||||
|
@ -244,21 +243,24 @@ const renderCodeForm = remove => code => (
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
|
||||||
const renderFile = (e, file) => (
|
const renderFile = (e, file, quest) => {
|
||||||
<div key={file ? file.uid : null}>
|
console.log(file)
|
||||||
|
return (
|
||||||
|
<div key={file ? file.uid : null}>
|
||||||
{e}
|
{e}
|
||||||
{file && file.response && file.response.uuid
|
{file && file.response && file.response.uuid
|
||||||
? <>Код для вставки: <pre>![](/api/file/{file.response.uuid})</pre></>
|
? <>Код для вставки: <pre>![](/file/{quest.id}/{file.originFileObj.name})</pre></>
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const renderFileItem = (file) => (
|
const renderFileItem = (file, quest) => (
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Item.Meta
|
<List.Item.Meta
|
||||||
avatar={<Avatar src={`/api/file/${file.id}`} />}
|
avatar={<Avatar src={`/file/${quest.id})/${file.originalName}`} />}
|
||||||
title={file.originalName}
|
title={file.originalName}
|
||||||
description={<>Код для вставки: <pre>![](/api/file/{file.id})</pre></>}
|
description={<>Код для вставки: <pre>![](/file/{quest.id}/{file.originalName})</pre></>}
|
||||||
/>
|
/>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ const manifest = {
|
||||||
workbox: {
|
workbox: {
|
||||||
cleanupOutdatedCaches: true
|
cleanupOutdatedCaches: true
|
||||||
},
|
},
|
||||||
|
base: 'assets',
|
||||||
manifest: {
|
manifest: {
|
||||||
name: 'NQuest',
|
name: 'NQuest',
|
||||||
short_name: 'NQuest',
|
short_name: 'NQuest',
|
||||||
|
@ -80,6 +81,12 @@ export default defineConfig({
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
ws: false
|
ws: false
|
||||||
|
},
|
||||||
|
'/file': {
|
||||||
|
target: 'http://localhost:8000',
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false,
|
||||||
|
ws: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
8
main.go
8
main.go
|
@ -127,12 +127,12 @@ func main() {
|
||||||
|
|
||||||
api.RegisterHandlersWithBaseURL(codegen, handler, "/api")
|
api.RegisterHandlersWithBaseURL(codegen, handler, "/api")
|
||||||
|
|
||||||
e.FileFS("/", "index.html", distIndexHtml)
|
|
||||||
e.FileFS("/*", "index.html", distIndexHtml)
|
|
||||||
e.StaticFS("/", distDirFS)
|
|
||||||
|
|
||||||
// --[ System ]--
|
// --[ System ]--
|
||||||
e.GET("/metrics", echoprometheus.NewHandler())
|
e.GET("/metrics", echoprometheus.NewHandler())
|
||||||
|
|
||||||
|
e.StaticFS("/file", afero.NewIOFS(storage))
|
||||||
|
e.StaticFS("/*", distDirFS)
|
||||||
|
|
||||||
e.Logger.Debugf("backend version %s", Version)
|
e.Logger.Debugf("backend version %s", Version)
|
||||||
e.Logger.Fatal(e.Start(cfg.Listen))
|
e.Logger.Fatal(e.Start(cfg.Listen))
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ func (a *Admin) AdminEditGame(ctx echo.Context) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
tasks = append(tasks, api.TaskEdit{
|
tasks = append(tasks, api.TaskEdit{
|
||||||
Id: &t.ID,
|
Id: t.ID,
|
||||||
Codes: codes,
|
Codes: codes,
|
||||||
Text: t.Text,
|
Text: t.Text,
|
||||||
Title: t.Title,
|
Title: t.Title,
|
||||||
|
@ -98,7 +98,7 @@ func (a *Admin) AdminGetGame(ctx echo.Context, uid uuid.UUID) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
tasks = append(tasks, api.TaskEdit{
|
tasks = append(tasks, api.TaskEdit{
|
||||||
Id: &t.ID,
|
Id: t.ID,
|
||||||
Codes: codes,
|
Codes: codes,
|
||||||
Text: t.Text,
|
Text: t.Text,
|
||||||
Title: t.Title,
|
Title: t.Title,
|
||||||
|
@ -163,12 +163,8 @@ func (*Admin) mapCreateGameRequest(req *api.GameEdit, user *models.User) *models
|
||||||
IconID: req.Icon,
|
IconID: req.Icon,
|
||||||
}
|
}
|
||||||
for order, te := range req.Tasks {
|
for order, te := range req.Tasks {
|
||||||
id := uuid.New()
|
|
||||||
if te.Id != nil {
|
|
||||||
id = *te.Id
|
|
||||||
}
|
|
||||||
task := &models.Task{
|
task := &models.Task{
|
||||||
ID: id,
|
ID: te.Id,
|
||||||
Title: te.Title,
|
Title: te.Title,
|
||||||
Text: te.Text,
|
Text: te.Text,
|
||||||
Codes: make([]*models.Code, 0, len(te.Codes)),
|
Codes: make([]*models.Code, 0, len(te.Codes)),
|
||||||
|
|
|
@ -40,16 +40,6 @@ func (u *File) AdminUploadFile(c echo.Context, quest uuid.UUID) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// (GET /file/{uid})
|
|
||||||
func (u *File) GetFile(c echo.Context, uid uuid.UUID) error {
|
|
||||||
f, rdr, err := u.FileService.GetFile(c.Request().Context(), uid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Stream(200, f.ContentType, rdr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *File) AdminListFiles(c echo.Context, quest uuid.UUID) error {
|
func (u *File) AdminListFiles(c echo.Context, quest uuid.UUID) error {
|
||||||
fl, err := u.FileService.GetFilesByQuest(c.Request().Context(), quest)
|
fl, err := u.FileService.GetFilesByQuest(c.Request().Context(), quest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,6 +10,7 @@ type Task struct {
|
||||||
Title string
|
Title string
|
||||||
Text string
|
Text string
|
||||||
MaxTime int
|
MaxTime int
|
||||||
|
Game *Game
|
||||||
GameID uuid.UUID
|
GameID uuid.UUID
|
||||||
Codes []*Code `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
|
Codes []*Code `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
|
||||||
TaskOrder uint
|
TaskOrder uint
|
||||||
|
|
|
@ -3,7 +3,6 @@ package service
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -53,21 +52,6 @@ func (u *File) Upload(
|
||||||
return file.ID, u.DB.WithContext(ctx).Create(file).Error
|
return file.ID, u.DB.WithContext(ctx).Create(file).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *File) GetFile(ctx context.Context, uid uuid.UUID) (*models.File, io.ReadCloser, error) {
|
|
||||||
f := new(models.File)
|
|
||||||
if err := u.DB.WithContext(ctx).First(f, uid).Error; err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath := fmt.Sprintf("%s/%s", f.QuestID.String(), f.Filename)
|
|
||||||
file, err := u.store.Open(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return f, file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *File) GetFilesByQuest(ctx context.Context, quest uuid.UUID) ([]*models.File, error) {
|
func (u *File) GetFilesByQuest(ctx context.Context, quest uuid.UUID) ([]*models.File, error) {
|
||||||
list := make([]*models.File, 0)
|
list := make([]*models.File, 0)
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,14 @@ func (gs *Game) ListByAuthor(ctx context.Context, author *models.User) ([]*model
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *Game) UpsertGame(ctx context.Context, game *models.Game) (*models.Game, error) {
|
func (gs *Game) UpsertGame(ctx context.Context, game *models.Game) (*models.Game, error) {
|
||||||
return game, gs.DB.Debug().
|
|
||||||
|
ids := []uuid.UUID{}
|
||||||
|
for _, t := range game.Tasks {
|
||||||
|
ids = append(ids, t.ID)
|
||||||
|
}
|
||||||
|
gs.DB.Delete([]models.Task{}, `game_id = ? and id not in (?)`, game.ID, ids)
|
||||||
|
|
||||||
|
err := gs.DB.
|
||||||
Session(&gorm.Session{FullSaveAssociations: true}).
|
Session(&gorm.Session{FullSaveAssociations: true}).
|
||||||
Clauses(clause.OnConflict{
|
Clauses(clause.OnConflict{
|
||||||
Columns: []clause.Column{{Name: "id"}},
|
Columns: []clause.Column{{Name: "id"}},
|
||||||
|
@ -76,6 +83,11 @@ func (gs *Game) UpsertGame(ctx context.Context, game *models.Game) (*models.Game
|
||||||
"title", "description",
|
"title", "description",
|
||||||
}),
|
}),
|
||||||
}).
|
}).
|
||||||
Create(&game).
|
Create(game).
|
||||||
Error
|
Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return game, gs.DB.Save(game).Error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue