Нормальная загрузка файлов
|
@ -1,7 +0,0 @@
|
||||||
POSTGRES_HOSTNAME=localhost
|
|
||||||
POSTGRES_DB=nquest
|
|
||||||
POSTGRES_USER=nquest
|
|
||||||
POSTGRES_PASSWORD=nquest
|
|
||||||
POSTGRES_PORT=5432
|
|
||||||
SECRET=s3cr3t
|
|
||||||
LISTEN=:8000
|
|
|
@ -1 +0,0 @@
|
||||||
FROM gitrepo.ru/neonxp/devcontainer:latest
|
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"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": {}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres-data:
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
volumes:
|
|
||||||
- ../..:/workspaces:cached
|
|
||||||
- ${SSH_AUTH_SOCK}:/tmp/ssh-agent.socket
|
|
||||||
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
|
|
2
.vscode/launch.json
vendored
|
@ -10,7 +10,7 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "${workspaceFolder}/",
|
"program": "${workspaceFolder}/",
|
||||||
"envFile": "${workspaceFolder}/.devcontainer/.env"
|
"envFile": "${workspaceFolder}/dev/.env"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
12
Makefile
|
@ -8,8 +8,16 @@ generate:
|
||||||
|
|
||||||
.PHONY: build-front
|
.PHONY: build-front
|
||||||
build-front:
|
build-front:
|
||||||
cd frontend & npm run
|
cd frontend
|
||||||
|
npm run build
|
||||||
|
|
||||||
.PHONY: dev-front
|
.PHONY: dev-front
|
||||||
dev-front:
|
dev-front:
|
||||||
cd frontend; npm run dev
|
cd frontend
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
.PHONY: deploy
|
||||||
|
deploy: frontend/dist
|
||||||
|
docker context use curie
|
||||||
|
docker compose up -d
|
||||||
|
docker context use default
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/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 go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen -generate types -package api -o ./types.go ./openapi.yaml
|
//go:generate oapi-codegen -generate types -package api -o ./types.go ./openapi.yaml
|
||||||
|
|
|
@ -128,11 +128,18 @@ paths:
|
||||||
format: binary
|
format: binary
|
||||||
|
|
||||||
# Admin routes
|
# Admin routes
|
||||||
/admin/file/upload:
|
/admin/file/{quest}/upload:
|
||||||
post:
|
post:
|
||||||
operationId: adminUploadFile
|
operationId: adminUploadFile
|
||||||
security:
|
security:
|
||||||
- cookieAuth: [creator, admin]
|
- cookieAuth: [creator, admin]
|
||||||
|
parameters:
|
||||||
|
- name: quest
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
requestBody:
|
requestBody:
|
||||||
content:
|
content:
|
||||||
multipart/form-data:
|
multipart/form-data:
|
||||||
|
@ -145,6 +152,22 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
$ref: "#/components/responses/uploadResponse"
|
$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:
|
/admin/games:
|
||||||
get:
|
get:
|
||||||
operationId: adminListGames
|
operationId: adminListGames
|
||||||
|
@ -225,6 +248,8 @@ components:
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
|
visible:
|
||||||
|
type: boolean
|
||||||
title:
|
title:
|
||||||
type: string
|
type: string
|
||||||
description:
|
description:
|
||||||
|
@ -316,7 +341,6 @@ components:
|
||||||
- type
|
- type
|
||||||
- tasks
|
- tasks
|
||||||
- points
|
- points
|
||||||
- icon
|
|
||||||
taskEdit:
|
taskEdit:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -353,6 +377,20 @@ components:
|
||||||
enum:
|
enum:
|
||||||
- virtual
|
- virtual
|
||||||
- city
|
- city
|
||||||
|
fileItem:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
originalName:
|
||||||
|
type: string
|
||||||
|
size:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- originalName
|
||||||
|
- size
|
||||||
responses:
|
responses:
|
||||||
userResponse:
|
userResponse:
|
||||||
description: ""
|
description: ""
|
||||||
|
@ -410,6 +448,14 @@ components:
|
||||||
format: uuid
|
format: uuid
|
||||||
required:
|
required:
|
||||||
- uuid
|
- uuid
|
||||||
|
filesListResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/fileItem"
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
cookieAuth:
|
cookieAuth:
|
||||||
type: apiKey
|
type: apiKey
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Package api provides primitives to interact with the openapi HTTP API.
|
// Package api provides primitives to interact with the openapi HTTP API.
|
||||||
//
|
//
|
||||||
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0 DO NOT EDIT.
|
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.1.0 DO NOT EDIT.
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -22,8 +22,11 @@ import (
|
||||||
// ServerInterface represents all server handlers.
|
// ServerInterface represents all server handlers.
|
||||||
type ServerInterface interface {
|
type ServerInterface interface {
|
||||||
|
|
||||||
// (POST /admin/file/upload)
|
// (GET /admin/file/{quest})
|
||||||
AdminUploadFile(ctx echo.Context) error
|
AdminListFiles(ctx echo.Context, quest openapi_types.UUID) error
|
||||||
|
|
||||||
|
// (POST /admin/file/{quest}/upload)
|
||||||
|
AdminUploadFile(ctx echo.Context, quest openapi_types.UUID) error
|
||||||
|
|
||||||
// (GET /admin/games)
|
// (GET /admin/games)
|
||||||
AdminListGames(ctx echo.Context) error
|
AdminListGames(ctx echo.Context) error
|
||||||
|
@ -64,14 +67,39 @@ type ServerInterfaceWrapper struct {
|
||||||
Handler ServerInterface
|
Handler ServerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminUploadFile converts echo context to params.
|
// AdminListFiles converts echo context to params.
|
||||||
func (w *ServerInterfaceWrapper) AdminUploadFile(ctx echo.Context) error {
|
func (w *ServerInterfaceWrapper) AdminListFiles(ctx echo.Context) error {
|
||||||
var err error
|
var err error
|
||||||
|
// ------------- Path parameter "quest" -------------
|
||||||
|
var quest openapi_types.UUID
|
||||||
|
|
||||||
|
err = runtime.BindStyledParameterWithOptions("simple", "quest", ctx.Param("quest"), &quest, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter quest: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
|
ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshaled arguments
|
// Invoke the callback with all the unmarshaled arguments
|
||||||
err = w.Handler.AdminUploadFile(ctx)
|
err = w.Handler.AdminListFiles(ctx, quest)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminUploadFile converts echo context to params.
|
||||||
|
func (w *ServerInterfaceWrapper) AdminUploadFile(ctx echo.Context) error {
|
||||||
|
var err error
|
||||||
|
// ------------- Path parameter "quest" -------------
|
||||||
|
var quest openapi_types.UUID
|
||||||
|
|
||||||
|
err = runtime.BindStyledParameterWithOptions("simple", "quest", ctx.Param("quest"), &quest, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter quest: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Set(CookieAuthScopes, []string{"creator", "admin"})
|
||||||
|
|
||||||
|
// Invoke the callback with all the unmarshaled arguments
|
||||||
|
err = w.Handler.AdminUploadFile(ctx, quest)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +131,7 @@ func (w *ServerInterfaceWrapper) AdminGetGame(ctx echo.Context) error {
|
||||||
// ------------- Path parameter "uid" -------------
|
// ------------- Path parameter "uid" -------------
|
||||||
var uid openapi_types.UUID
|
var uid openapi_types.UUID
|
||||||
|
|
||||||
err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid)
|
err = runtime.BindStyledParameterWithOptions("simple", "uid", ctx.Param("uid"), &uid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
||||||
}
|
}
|
||||||
|
@ -121,7 +149,7 @@ func (w *ServerInterfaceWrapper) GameEngine(ctx echo.Context) error {
|
||||||
// ------------- Path parameter "uid" -------------
|
// ------------- Path parameter "uid" -------------
|
||||||
var uid openapi_types.UUID
|
var uid openapi_types.UUID
|
||||||
|
|
||||||
err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid)
|
err = runtime.BindStyledParameterWithOptions("simple", "uid", ctx.Param("uid"), &uid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
||||||
}
|
}
|
||||||
|
@ -139,7 +167,7 @@ func (w *ServerInterfaceWrapper) EnterCode(ctx echo.Context) error {
|
||||||
// ------------- Path parameter "uid" -------------
|
// ------------- Path parameter "uid" -------------
|
||||||
var uid openapi_types.UUID
|
var uid openapi_types.UUID
|
||||||
|
|
||||||
err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid)
|
err = runtime.BindStyledParameterWithOptions("simple", "uid", ctx.Param("uid"), &uid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
||||||
}
|
}
|
||||||
|
@ -157,7 +185,7 @@ func (w *ServerInterfaceWrapper) GetFile(ctx echo.Context) error {
|
||||||
// ------------- Path parameter "uid" -------------
|
// ------------- Path parameter "uid" -------------
|
||||||
var uid openapi_types.UUID
|
var uid openapi_types.UUID
|
||||||
|
|
||||||
err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid)
|
err = runtime.BindStyledParameterWithOptions("simple", "uid", ctx.Param("uid"), &uid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter uid: %s", err))
|
||||||
}
|
}
|
||||||
|
@ -248,7 +276,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
||||||
Handler: si,
|
Handler: si,
|
||||||
}
|
}
|
||||||
|
|
||||||
router.POST(baseURL+"/admin/file/upload", wrapper.AdminUploadFile)
|
router.GET(baseURL+"/admin/file/:quest", wrapper.AdminListFiles)
|
||||||
|
router.POST(baseURL+"/admin/file/:quest/upload", wrapper.AdminUploadFile)
|
||||||
router.GET(baseURL+"/admin/games", wrapper.AdminListGames)
|
router.GET(baseURL+"/admin/games", wrapper.AdminListGames)
|
||||||
router.POST(baseURL+"/admin/games", wrapper.AdminEditGame)
|
router.POST(baseURL+"/admin/games", wrapper.AdminEditGame)
|
||||||
router.GET(baseURL+"/admin/games/:uid", wrapper.AdminGetGame)
|
router.GET(baseURL+"/admin/games/:uid", wrapper.AdminGetGame)
|
||||||
|
@ -266,26 +295,27 @@ 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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",
|
||||||
"sJhOGdW6+j8AAP//fdZwRK4ZAAA=",
|
"cOcQWHfwVgXOApzkeva/610QMlPEMRjzS6X6UIt3NmrYCIOOv+NWfqolfygzdh/feL/OH/c8k16zb3uX",
|
||||||
|
"n5trox3ImoqyAf1Yl/1CpyxiIY185br8PwAA//96RTU+mhwAAA==",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
|
15
api/types.go
|
@ -1,6 +1,6 @@
|
||||||
// Package api provides primitives to interact with the openapi HTTP API.
|
// Package api provides primitives to interact with the openapi HTTP API.
|
||||||
//
|
//
|
||||||
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0 DO NOT EDIT.
|
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.1.0 DO NOT EDIT.
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -46,10 +46,17 @@ type CodeView struct {
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileItem defines model for fileItem.
|
||||||
|
type FileItem struct {
|
||||||
|
Id openapi_types.UUID `json:"id"`
|
||||||
|
OriginalName string `json:"originalName"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
// GameEdit defines model for gameEdit.
|
// GameEdit defines model for gameEdit.
|
||||||
type GameEdit struct {
|
type GameEdit struct {
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Icon openapi_types.UUID `json:"icon"`
|
Icon *openapi_types.UUID `json:"icon,omitempty"`
|
||||||
Id *openapi_types.UUID `json:"id,omitempty"`
|
Id *openapi_types.UUID `json:"id,omitempty"`
|
||||||
Points int `json:"points"`
|
Points int `json:"points"`
|
||||||
Tasks []TaskEdit `json:"tasks"`
|
Tasks []TaskEdit `json:"tasks"`
|
||||||
|
@ -72,6 +79,7 @@ type GameView struct {
|
||||||
TaskCount int `json:"taskCount"`
|
TaskCount int `json:"taskCount"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Type GameType `json:"type"`
|
Type GameType `json:"type"`
|
||||||
|
Visible *bool `json:"visible,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TaskEdit defines model for taskEdit.
|
// TaskEdit defines model for taskEdit.
|
||||||
|
@ -115,6 +123,9 @@ type ErrorResponse struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilesListResponse defines model for filesListResponse.
|
||||||
|
type FilesListResponse = []FileItem
|
||||||
|
|
||||||
// GameAdminResponse defines model for gameAdminResponse.
|
// GameAdminResponse defines model for gameAdminResponse.
|
||||||
type GameAdminResponse = GameEdit
|
type GameAdminResponse = GameEdit
|
||||||
|
|
||||||
|
|
15
dev/docker-compose.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:15-alpine3.17
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
|
@ -4,6 +4,16 @@ volumes:
|
||||||
postgres-data:
|
postgres-data:
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- 8989:8989
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
db:
|
db:
|
||||||
image: postgres:15-alpine3.17
|
image: postgres:15-alpine3.17
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
@ -11,5 +21,3 @@ services:
|
||||||
- postgres-data:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
|
|
|
@ -51,7 +51,13 @@ const router = createBrowserRouter(
|
||||||
<Route
|
<Route
|
||||||
path="/admin/quests/:gameId"
|
path="/admin/quests/:gameId"
|
||||||
element={<Auth role="creator"><EditQuest /></Auth>}
|
element={<Auth role="creator"><EditQuest /></Auth>}
|
||||||
loader={({ params }) => ajax(`/api/admin/games/${params.gameId}`)}
|
loader={async ({ params }) => {
|
||||||
|
const quest = await ajax(`/api/admin/games/${params.gameId}`)
|
||||||
|
const files = await ajax(`/api/admin/file/${params.gameId}`)
|
||||||
|
|
||||||
|
return { quest, files }
|
||||||
|
}
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/admin/quests"
|
path="/admin/quests"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
:root {
|
:root {
|
||||||
--accent-color: #fb923c;
|
--accent-color: #59FBEA;
|
||||||
--primary-bg: #171E26;
|
--primary-bg: #171E26;
|
||||||
--secondary-bg: #26323f;
|
--secondary-bg: #26323f;
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,13 @@ ReactDOM.createRoot(document.getElementById('root')).render(
|
||||||
locale={ruRU}
|
locale={ruRU}
|
||||||
theme={{
|
theme={{
|
||||||
token: {
|
token: {
|
||||||
colorPrimary: '#fb923c',
|
colorTextBase: '#fff',
|
||||||
colorInfo: '#fb923c',
|
colorPrimary: '#59FBEA',
|
||||||
|
colorButtonText: '#000',
|
||||||
|
colorInfo: '#59FBEA',
|
||||||
colorSuccess: '#15803d',
|
colorSuccess: '#15803d',
|
||||||
colorBgBase: '#171e26',
|
colorBgBase: '#171e26',
|
||||||
borderRadius: 3,
|
borderRadius: 2,
|
||||||
wireframe: false
|
wireframe: false
|
||||||
},
|
},
|
||||||
algorithm: darkAlgorithm
|
algorithm: darkAlgorithm
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
import { useLoaderData, useNavigate } from 'react-router-dom'
|
import { useLoaderData, useNavigate } from 'react-router-dom'
|
||||||
import { Alert, Avatar, Button, Card, Form, Input, InputNumber, Popconfirm, Radio, Switch, Typography, Upload } from 'antd'
|
import { Alert, Avatar, Button, Card, Col, Form, Input, InputNumber, List, Modal, Popconfirm, Radio, Row, Switch, Typography, Upload } from 'antd'
|
||||||
import { UploadOutlined, PlusOutlined, CloseOutlined } from '@ant-design/icons'
|
import { UploadOutlined, PlusOutlined, CloseOutlined } from '@ant-design/icons'
|
||||||
import { ajax } from '../../utils/fetch'
|
import { ajax } from '../../utils/fetch'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { uuidv4 } from '../../utils/uuid'
|
||||||
|
import Markdown from 'react-markdown'
|
||||||
|
|
||||||
const { Title } = Typography
|
const { Title } = Typography
|
||||||
|
|
||||||
const Quest = () => {
|
const Quest = () => {
|
||||||
let quest = useLoaderData()
|
let { quest, files } = useLoaderData()
|
||||||
const [error, setError] = useState()
|
const [error, setError] = useState()
|
||||||
|
if (!quest) {
|
||||||
|
quest = {
|
||||||
|
type: 'city',
|
||||||
|
points: 10,
|
||||||
|
tasks: [],
|
||||||
|
id: uuidv4(),
|
||||||
|
visible: false,
|
||||||
|
title: '',
|
||||||
|
description: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [fields, setFields] = useState(quest)
|
||||||
|
const [preview, setPreview] = useState(false)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const normFile = (e) => {
|
const normFile = (e) => {
|
||||||
if (Array.isArray(e)) {
|
if (Array.isArray(e)) {
|
||||||
|
@ -42,27 +57,28 @@ const Quest = () => {
|
||||||
.catch(({ message }) => setError('Ошибка создания'))
|
.catch(({ message }) => setError('Ошибка создания'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quest) {
|
|
||||||
quest = {
|
|
||||||
type: 'city',
|
|
||||||
points: 10,
|
|
||||||
tasks: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title>{quest.title ? (quest.title) : ('Новый квест')}</Title>
|
<Title>{quest.title ? (quest.title) : ('Новый квест')}</Title>
|
||||||
{error ? <Alert type="error" message={error} /> : null}
|
{error ? <Alert type="error" message={error} /> : null}
|
||||||
|
<Row gutter={8}>
|
||||||
|
<Col xs={24} sm={16} md={16}>
|
||||||
<Form
|
<Form
|
||||||
initialValues={quest}
|
initialValues={quest}
|
||||||
onFinish={onFinish}
|
onFinish={onFinish}
|
||||||
{...formItemLayout}
|
{...formItemLayout}
|
||||||
|
onValuesChange={(_, allFields) => setFields(allFields)}
|
||||||
>
|
>
|
||||||
<Form.Item wrapperCol={buttonLayout}>
|
<Form.Item wrapperCol={buttonLayout}>
|
||||||
|
<Button.Group block>
|
||||||
<Button type='primary' htmlType='submit' block>
|
<Button type='primary' htmlType='submit' block>
|
||||||
Сохранить квест
|
Сохранить квест
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button type='default' block onClick={() => setPreview(true)}>
|
||||||
|
Предпросмотр
|
||||||
|
</Button>
|
||||||
|
</Button.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name='id' hidden>
|
<Form.Item name='id' hidden>
|
||||||
<Input />
|
<Input />
|
||||||
|
@ -82,7 +98,7 @@ const Quest = () => {
|
||||||
getValueFromEvent={normFile}
|
getValueFromEvent={normFile}
|
||||||
>
|
>
|
||||||
{quest.icon ? <Avatar src={`/api/file/${quest.icon}`} /> : null}
|
{quest.icon ? <Avatar src={`/api/file/${quest.icon}`} /> : null}
|
||||||
<Upload name='file' action='/api/admin/file/upload' listType='picture' maxCount={1}>
|
<Upload name='file' action={`/api/admin/file/${quest.id}/upload`} listType='picture' maxCount={1}>
|
||||||
<Button icon={<UploadOutlined />}>Загрузка</Button>
|
<Button icon={<UploadOutlined />}>Загрузка</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -108,6 +124,47 @@ const Quest = () => {
|
||||||
)}
|
)}
|
||||||
</Form.List>
|
</Form.List>
|
||||||
</Form>
|
</Form>
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={8} md={8}>
|
||||||
|
<Title>Файлы</Title>
|
||||||
|
<Upload
|
||||||
|
name='file'
|
||||||
|
action={`/api/admin/file/${quest.id}/upload`}
|
||||||
|
listType='picture'
|
||||||
|
maxCount={10}
|
||||||
|
itemRender={renderFile}
|
||||||
|
>
|
||||||
|
<Button icon={<UploadOutlined />}>Загрузка</Button>
|
||||||
|
</Upload>
|
||||||
|
Ранее загруженные файлы:
|
||||||
|
<List dataSource={files} renderItem={renderFileItem} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Modal
|
||||||
|
title="Предпросмотр квеста"
|
||||||
|
open={preview}
|
||||||
|
footer={<Button onClick={() => setPreview(false)}>Закрыть</Button>}
|
||||||
|
width={'80%'}
|
||||||
|
centered
|
||||||
|
>
|
||||||
|
<List dataSource={fields.tasks} renderItem={(task) => (
|
||||||
|
<List.Item key={task.id}>
|
||||||
|
<List.Item.Meta
|
||||||
|
title={task.title}
|
||||||
|
description={
|
||||||
|
<><Card>
|
||||||
|
<Markdown>{task.text}</Markdown>
|
||||||
|
</Card>
|
||||||
|
Коды:
|
||||||
|
<ul>
|
||||||
|
{task.codes.map(c => <li key={c.key}>{c.code}</li>)}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</List.Item>
|
||||||
|
)} />
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -187,4 +244,24 @@ const renderCodeForm = remove => code => (
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const renderFile = (e, file) => (
|
||||||
|
<div key={file ? file.uid : null}>
|
||||||
|
{e}
|
||||||
|
{file && file.response && file.response.uuid
|
||||||
|
? <>Код для вставки: <pre>![](/api/file/{file.response.uuid})</pre></>
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderFileItem = (file) => (
|
||||||
|
<List.Item>
|
||||||
|
<List.Item.Meta
|
||||||
|
avatar={<Avatar src={`/api/file/${file.id}`} />}
|
||||||
|
title={file.originalName}
|
||||||
|
description={<>Код для вставки: <pre>![](/api/file/{file.id})</pre></>}
|
||||||
|
/>
|
||||||
|
</List.Item>
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
export default Quest
|
export default Quest
|
||||||
|
|
|
@ -15,15 +15,16 @@ const Quests = () => {
|
||||||
rowKey={'id'}
|
rowKey={'id'}
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
title: 'UUID',
|
title: 'Опубликован?',
|
||||||
dataIndex: 'id',
|
dataIndex: 'visible',
|
||||||
key: 'id',
|
key: 'visible',
|
||||||
render: uid => <Link to={`/admin/quests/${uid}`}>${uid}</Link>
|
render: visible => visible ? 'Да' : 'Нет'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Название',
|
title: 'Название',
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
key: 'title'
|
key: 'title',
|
||||||
|
render: (title, q) => <Link to={`/admin/quests/${q.id}`}>{title}</Link>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Тип',
|
title: 'Тип',
|
||||||
|
|
5
frontend/src/utils/uuid.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export function uuidv4 () {
|
||||||
|
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>
|
||||||
|
(+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
|
||||||
|
)
|
||||||
|
};
|
|
@ -62,7 +62,7 @@ const manifest = {
|
||||||
purpose: 'maskable any'
|
purpose: 'maskable any'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
theme_color: '#fb923c',
|
theme_color: '#59FBEA',
|
||||||
background_color: '#171e26',
|
background_color: '#171e26',
|
||||||
display: 'standalone',
|
display: 'standalone',
|
||||||
scope: '/',
|
scope: '/',
|
||||||
|
|
25
go.mod
|
@ -5,21 +5,20 @@ go 1.21.3
|
||||||
require (
|
require (
|
||||||
github.com/dimuska139/go-email-normalizer v1.2.1
|
github.com/dimuska139/go-email-normalizer v1.2.1
|
||||||
github.com/getkin/kin-openapi v0.120.0
|
github.com/getkin/kin-openapi v0.120.0
|
||||||
|
github.com/google/uuid v1.5.0
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/labstack/echo-contrib v0.15.0
|
github.com/labstack/echo-contrib v0.15.0
|
||||||
github.com/labstack/echo/v4 v4.11.2
|
github.com/labstack/echo/v4 v4.11.4
|
||||||
github.com/oapi-codegen/runtime v1.0.0
|
github.com/oapi-codegen/runtime v1.1.1
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.17.0
|
||||||
gorm.io/driver/postgres v1.5.3
|
gorm.io/driver/postgres v1.5.3
|
||||||
gorm.io/gorm v1.25.5
|
gorm.io/gorm v1.25.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||||
github.com/deepmap/oapi-codegen/v2 v2.0.0 // indirect
|
|
||||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||||
github.com/go-openapi/swag v0.22.4 // indirect
|
github.com/go-openapi/swag v0.22.4 // indirect
|
||||||
github.com/google/uuid v1.3.1 // indirect
|
|
||||||
github.com/gorilla/context v1.1.1 // indirect
|
github.com/gorilla/context v1.1.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||||
|
@ -29,9 +28,6 @@ require (
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||||
golang.org/x/mod v0.12.0 // indirect
|
|
||||||
golang.org/x/tools v0.12.0 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,21 +42,22 @@ require (
|
||||||
github.com/jackc/pgx/v5 v5.4.3
|
github.com/jackc/pgx/v5 v5.4.3
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/labstack/gommon v0.4.0 // indirect
|
github.com/labstack/gommon v0.4.2 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/oapi-codegen/echo-middleware v1.0.1
|
github.com/oapi-codegen/echo-middleware v1.0.1
|
||||||
github.com/prometheus/client_golang v1.15.0 // indirect
|
github.com/prometheus/client_golang v1.15.0 // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.42.0 // indirect
|
github.com/prometheus/common v0.42.0 // indirect
|
||||||
github.com/prometheus/procfs v0.9.0 // indirect
|
github.com/prometheus/procfs v0.9.0 // indirect
|
||||||
|
github.com/spf13/afero v1.11.0
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
github.com/wader/gormstore/v2 v2.0.3
|
github.com/wader/gormstore/v2 v2.0.3
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/net v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.15.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
57
go.sum
|
@ -16,8 +16,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/deepmap/oapi-codegen/v2 v2.0.0 h1:3TS7w3r+XnjKFXcbFbc16pTWzfTy0OLPkCsutEHjWDA=
|
|
||||||
github.com/deepmap/oapi-codegen/v2 v2.0.0/go.mod h1:7zR+ZL3WzLeCkr2k8oWTxEa0v8y/F25ane0l6A5UjLA=
|
|
||||||
github.com/dimuska139/go-email-normalizer v1.2.1 h1:pJNZnU7uS9MRoYqpoir05B+bCYXrS9sPGE4G1o9EDA8=
|
github.com/dimuska139/go-email-normalizer v1.2.1 h1:pJNZnU7uS9MRoYqpoir05B+bCYXrS9sPGE4G1o9EDA8=
|
||||||
github.com/dimuska139/go-email-normalizer v1.2.1/go.mod h1:fGPWcd/7PSz9aOHusKVYmDk+oKahH/fZTCQ7tTU7e0Y=
|
github.com/dimuska139/go-email-normalizer v1.2.1/go.mod h1:fGPWcd/7PSz9aOHusKVYmDk+oKahH/fZTCQ7tTU7e0Y=
|
||||||
github.com/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg=
|
github.com/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg=
|
||||||
|
@ -46,8 +44,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
|
@ -125,10 +123,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/labstack/echo-contrib v0.15.0 h1:9K+oRU265y4Mu9zpRDv3X+DGTqUALY6oRHCSZZKCRVU=
|
github.com/labstack/echo-contrib v0.15.0 h1:9K+oRU265y4Mu9zpRDv3X+DGTqUALY6oRHCSZZKCRVU=
|
||||||
github.com/labstack/echo-contrib v0.15.0/go.mod h1:lei+qt5CLB4oa7VHTE0yEfQSEB9XTJI1LUqko9UWvo4=
|
github.com/labstack/echo-contrib v0.15.0/go.mod h1:lei+qt5CLB4oa7VHTE0yEfQSEB9XTJI1LUqko9UWvo4=
|
||||||
github.com/labstack/echo/v4 v4.11.2 h1:T+cTLQxWCDfqDEoydYm5kCobjmHwOwcv4OJAPHilmdE=
|
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
|
||||||
github.com/labstack/echo/v4 v4.11.2/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
|
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
||||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
@ -137,16 +135,14 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||||
|
@ -155,8 +151,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
github.com/oapi-codegen/echo-middleware v1.0.1 h1:edYGScq1phCcuDoz9AqA9eHX+tEI1LNL5PL1lkkQh1k=
|
github.com/oapi-codegen/echo-middleware v1.0.1 h1:edYGScq1phCcuDoz9AqA9eHX+tEI1LNL5PL1lkkQh1k=
|
||||||
github.com/oapi-codegen/echo-middleware v1.0.1/go.mod h1:DBQKRn+D/vfXOFbaX5GRwFttoJY64JH6yu+pdt7wU3o=
|
github.com/oapi-codegen/echo-middleware v1.0.1/go.mod h1:DBQKRn+D/vfXOFbaX5GRwFttoJY64JH6yu+pdt7wU3o=
|
||||||
github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo=
|
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
|
||||||
github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A=
|
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
|
||||||
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
|
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
|
||||||
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
@ -182,6 +178,8 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz
|
||||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
|
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -203,7 +201,6 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d
|
||||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
|
||||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/wader/gormstore/v2 v2.0.3 h1:/29GWPauY8xZkpLnB8hsp+dZfP3ivA9fiDw1YVNTp6U=
|
github.com/wader/gormstore/v2 v2.0.3 h1:/29GWPauY8xZkpLnB8hsp+dZfP3ivA9fiDw1YVNTp6U=
|
||||||
|
@ -230,21 +227,19 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -260,13 +255,10 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -275,10 +267,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
@ -287,8 +279,6 @@ golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
|
|
||||||
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -306,10 +296,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
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=
|
||||||
|
|
6
main.go
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
oapiMiddleware "github.com/oapi-codegen/echo-middleware"
|
oapiMiddleware "github.com/oapi-codegen/echo-middleware"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"github.com/wader/gormstore/v2"
|
"github.com/wader/gormstore/v2"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
@ -51,11 +52,14 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storageFs := afero.NewOsFs()
|
||||||
|
storage := afero.NewBasePathFs(storageFs, "store")
|
||||||
|
|
||||||
// --[ Services ]--
|
// --[ Services ]--
|
||||||
userService := service.NewUser(db)
|
userService := service.NewUser(db)
|
||||||
gameService := service.NewGame(db)
|
gameService := service.NewGame(db)
|
||||||
engineService := service.NewEngine(db)
|
engineService := service.NewEngine(db)
|
||||||
uploadService := service.NewFile(db)
|
uploadService := service.NewFile(db, storage)
|
||||||
|
|
||||||
// --[ HTTP server ]--
|
// --[ HTTP server ]--
|
||||||
|
|
||||||
|
|
6
package-lock.json
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "nquest",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {}
|
||||||
|
}
|
|
@ -54,7 +54,7 @@ func (a *Admin) AdminEditGame(ctx echo.Context) error {
|
||||||
|
|
||||||
return ctx.JSON(http.StatusOK, api.GameAdminResponse{
|
return ctx.JSON(http.StatusOK, api.GameAdminResponse{
|
||||||
Description: game.Description,
|
Description: game.Description,
|
||||||
Icon: game.IconID,
|
Icon: &game.IconID,
|
||||||
Id: &game.ID,
|
Id: &game.ID,
|
||||||
Points: game.Points,
|
Points: game.Points,
|
||||||
Tasks: tasks,
|
Tasks: tasks,
|
||||||
|
@ -107,7 +107,7 @@ func (a *Admin) AdminGetGame(ctx echo.Context, uid uuid.UUID) error {
|
||||||
|
|
||||||
return ctx.JSON(http.StatusOK, api.GameAdminResponse{
|
return ctx.JSON(http.StatusOK, api.GameAdminResponse{
|
||||||
Description: game.Description,
|
Description: game.Description,
|
||||||
Icon: game.IconID,
|
Icon: &game.IconID,
|
||||||
Id: &game.ID,
|
Id: &game.ID,
|
||||||
Points: game.Points,
|
Points: game.Points,
|
||||||
Tasks: tasks,
|
Tasks: tasks,
|
||||||
|
@ -135,6 +135,7 @@ func (a *Admin) AdminListGames(ctx echo.Context) error {
|
||||||
TaskCount: len(game.Tasks),
|
TaskCount: len(game.Tasks),
|
||||||
CreatedAt: game.CreatedAt.Format(time.RFC3339),
|
CreatedAt: game.CreatedAt.Format(time.RFC3339),
|
||||||
Icon: game.IconID,
|
Icon: game.IconID,
|
||||||
|
Visible: &game.Visible,
|
||||||
}
|
}
|
||||||
resp = append(resp, gv)
|
resp = append(resp, gv)
|
||||||
}
|
}
|
||||||
|
@ -144,21 +145,25 @@ func (a *Admin) AdminListGames(ctx echo.Context) error {
|
||||||
|
|
||||||
func (*Admin) mapCreateGameRequest(req *api.GameEdit, user *models.User) *models.Game {
|
func (*Admin) mapCreateGameRequest(req *api.GameEdit, user *models.User) *models.Game {
|
||||||
id := uuid.New()
|
id := uuid.New()
|
||||||
|
icon := uuid.New()
|
||||||
if req.Id != nil {
|
if req.Id != nil {
|
||||||
id = *req.Id
|
id = *req.Id
|
||||||
}
|
}
|
||||||
|
if req.Icon != nil {
|
||||||
|
icon = *req.Icon
|
||||||
|
}
|
||||||
game := &models.Game{
|
game := &models.Game{
|
||||||
ID: id,
|
ID: id,
|
||||||
Visible: req.Visible,
|
Visible: req.Visible,
|
||||||
Title: req.Title,
|
Title: req.Title,
|
||||||
Description: req.Description,
|
Description: req.Description,
|
||||||
Authors: []*models.User{
|
Authors: []*models.User{
|
||||||
user,
|
// user,
|
||||||
},
|
},
|
||||||
Type: api.MapGameType(req.Type),
|
Type: api.MapGameType(req.Type),
|
||||||
Tasks: make([]*models.Task, 0, len(req.Tasks)),
|
Tasks: make([]*models.Task, 0, len(req.Tasks)),
|
||||||
Points: req.Points,
|
Points: req.Points,
|
||||||
IconID: req.Icon,
|
IconID: icon,
|
||||||
}
|
}
|
||||||
for order, te := range req.Tasks {
|
for order, te := range req.Tasks {
|
||||||
id := uuid.New()
|
id := uuid.New()
|
||||||
|
|
|
@ -12,7 +12,7 @@ type File struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// (POST /file/upload)
|
// (POST /file/upload)
|
||||||
func (u *File) AdminUploadFile(c echo.Context) error {
|
func (u *File) AdminUploadFile(c echo.Context, quest uuid.UUID) error {
|
||||||
// user := contextlib.GetUser(c)
|
// user := contextlib.GetUser(c)
|
||||||
fh, err := c.FormFile("file")
|
fh, err := c.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,6 +28,7 @@ func (u *File) AdminUploadFile(c echo.Context) error {
|
||||||
fh.Filename,
|
fh.Filename,
|
||||||
fh.Header.Get("Content-Type"),
|
fh.Header.Get("Content-Type"),
|
||||||
int(fh.Size),
|
int(fh.Size),
|
||||||
|
quest,
|
||||||
fo,
|
fo,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -41,10 +42,28 @@ func (u *File) AdminUploadFile(c echo.Context) error {
|
||||||
|
|
||||||
// (GET /file/{uid})
|
// (GET /file/{uid})
|
||||||
func (u *File) GetFile(c echo.Context, uid uuid.UUID) error {
|
func (u *File) GetFile(c echo.Context, uid uuid.UUID) error {
|
||||||
f, err := u.FileService.GetFile(c.Request().Context(), uid)
|
f, rdr, err := u.FileService.GetFile(c.Request().Context(), uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Blob(200, f.ContentType, f.Body)
|
return c.Stream(200, f.ContentType, rdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *File) AdminListFiles(c echo.Context, quest uuid.UUID) error {
|
||||||
|
fl, err := u.FileService.GetFilesByQuest(c.Request().Context(), quest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]api.FileItem, 0, len(fl))
|
||||||
|
for _, f := range fl {
|
||||||
|
list = append(list, api.FileItem{
|
||||||
|
Id: f.ID,
|
||||||
|
OriginalName: f.Filename,
|
||||||
|
Size: f.Size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(200, list)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ type File struct {
|
||||||
Filename string
|
Filename string
|
||||||
ContentType string
|
ContentType string
|
||||||
Size int
|
Size int
|
||||||
Body []byte `gorm:"type:bytea"`
|
QuestID uuid.UUID
|
||||||
CreatedAt time.Time `json:"-"`
|
CreatedAt time.Time `json:"-"`
|
||||||
UpdatedAt time.Time `json:"-"`
|
UpdatedAt time.Time `json:"-"`
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||||
|
|
|
@ -2,20 +2,25 @@ package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"gitrepo.ru/neonxp/nquest/pkg/models"
|
"gitrepo.ru/neonxp/nquest/pkg/models"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
DB *gorm.DB
|
DB *gorm.DB
|
||||||
|
store afero.Fs
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFile(db *gorm.DB) *File {
|
func NewFile(db *gorm.DB, store afero.Fs) *File {
|
||||||
return &File{
|
return &File{
|
||||||
DB: db,
|
DB: db,
|
||||||
|
store: store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,26 +29,47 @@ func (u *File) Upload(
|
||||||
filename string,
|
filename string,
|
||||||
contentType string,
|
contentType string,
|
||||||
size int,
|
size int,
|
||||||
|
questID uuid.UUID,
|
||||||
r multipart.File,
|
r multipart.File,
|
||||||
) (uuid.UUID, error) {
|
) (uuid.UUID, error) {
|
||||||
buf := make([]byte, size)
|
defer r.Close()
|
||||||
if _, err := r.Read(buf); err != nil {
|
|
||||||
return uuid.UUID{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
file := &models.File{
|
file := &models.File{
|
||||||
ID: uuid.New(),
|
ID: uuid.New(),
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
ContentType: contentType,
|
ContentType: contentType,
|
||||||
|
QuestID: questID,
|
||||||
Size: size,
|
Size: size,
|
||||||
Body: buf,
|
}
|
||||||
|
|
||||||
|
if err := u.store.MkdirAll(questID.String(), 0755); err != nil {
|
||||||
|
return file.ID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath := fmt.Sprintf("%s/%s", questID.String(), filename)
|
||||||
|
if err := afero.WriteReader(u.store, filePath, r); err != nil {
|
||||||
|
return file.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
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, error) {
|
func (u *File) GetFile(ctx context.Context, uid uuid.UUID) (*models.File, io.ReadCloser, error) {
|
||||||
f := new(models.File)
|
f := new(models.File)
|
||||||
|
if err := u.DB.WithContext(ctx).First(f, uid).Error; err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return f, u.DB.WithContext(ctx).First(f, uid).Error
|
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) {
|
||||||
|
list := make([]*models.File, 0)
|
||||||
|
|
||||||
|
return list, u.DB.WithContext(ctx).Find(&list, `quest_id = ?`, quest.String()).Error
|
||||||
}
|
}
|
||||||
|
|
0
store/.gitkeep
Normal file
BIN
store/d2c3f25b-9f35-4ea7-8039-69a0f7e6c5ac/logo.jpeg
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
store/d2c3f25b-9f35-4ea7-8039-69a0f7e6c5ac/logo.png
Normal file
After Width: | Height: | Size: 218 KiB |
13
store/d2c3f25b-9f35-4ea7-8039-69a0f7e6c5ac/logo.svg
Normal file
After Width: | Height: | Size: 414 KiB |
BIN
store/d2c3f25b-9f35-4ea7-8039-69a0f7e6c5ac/logo512.png
Normal file
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 3.9 MiB |
After Width: | Height: | Size: 3.7 MiB |
After Width: | Height: | Size: 12 KiB |