Compare commits
No commits in common. "5b18009658b5d56e945384558a8cc3a32e31b788" and "c0cb8269173e0a3b3158bc00c6f6d5d488ee953a" have entirely different histories.
5b18009658
...
c0cb826917
38 changed files with 185 additions and 1185 deletions
|
|
@ -5,11 +5,9 @@ allow:
|
|||
|
||||
components:
|
||||
domain: { in: internal/domain/** }
|
||||
repository: {in: internal/domain/repository/**}
|
||||
application: { in: internal/application/** }
|
||||
commands: { in: internal/application/}
|
||||
infrastructure: { in: internal/infrastructure/** }
|
||||
interface: { in: internal/interfaces/** }
|
||||
interface: { in: internal/interface/** }
|
||||
cmd: {in: cmd/**}
|
||||
|
||||
commonComponents:
|
||||
|
|
|
|||
72
cmd/main.go
72
cmd/main.go
|
|
@ -1,36 +1,31 @@
|
|||
package main
|
||||
|
||||
// @title 58team blog backend
|
||||
// @version 1.0
|
||||
// @description 58team blog's backend
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
// @contact.email support@swagger.io
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// @host localhost:8080
|
||||
// @BasePath /api/v1
|
||||
// @securityDefinitions.basic BasicAuth
|
||||
// @title 58team blog backend
|
||||
// @version 1.0
|
||||
// @description 58team blog's backend
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
// @contact.email support@swagger.io
|
||||
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// @host localhost:8080
|
||||
// @BasePath /api/v1
|
||||
|
||||
// @securityDefinitions.basic BasicAuth
|
||||
|
||||
import (
|
||||
docs "58team_blog/docs"
|
||||
"58team_blog/internal/application/services"
|
||||
"58team_blog/internal/infrastructure"
|
||||
"58team_blog/internal/infrastructure/db"
|
||||
"58team_blog/internal/infrastructure/db/repo"
|
||||
"58team_blog/internal/interfaces"
|
||||
"log"
|
||||
|
||||
"58team_blog/docs"
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"github.com/swaggo/files"
|
||||
"github.com/swaggo/gin-swagger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
router := gin.Default()
|
||||
|
||||
// Swagger setup
|
||||
docs.SwaggerInfo.Title = "58team blog"
|
||||
docs.SwaggerInfo.Description = "This is blog 58team"
|
||||
docs.SwaggerInfo.Version = "1.0"
|
||||
|
|
@ -38,33 +33,6 @@ func main() {
|
|||
docs.SwaggerInfo.BasePath = "/api/v1/"
|
||||
docs.SwaggerInfo.Schemes = []string{"http", "https"}
|
||||
|
||||
// router.GET("/swagger/*any", func(c *gin.Context) {
|
||||
// path := c.Param("any")
|
||||
// if strings.HasPrefix(path, "/doc.json") {
|
||||
// c.File("docs/swagger.json")
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
// })
|
||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, ginSwagger.URL("http://localhost:8080/swag/doc/doc.json")))
|
||||
router.StaticFile("/swag/doc/doc.json", "docs/swagger.json")
|
||||
|
||||
// Routes setup
|
||||
g := router.Group("/api/v1")
|
||||
|
||||
config, err := infrastructure.LoadConfig()
|
||||
if err != nil {
|
||||
log.Fatal("Load config error: ", err)
|
||||
}
|
||||
|
||||
d, err := db.DatabaseInit(*config)
|
||||
if err != nil {
|
||||
log.Fatal("Database error: ", err)
|
||||
}
|
||||
postRepository := repo.CreatePostRepository(d)
|
||||
|
||||
postService := services.CreatePostService(&postRepository)
|
||||
interfaces.BindPostAdmin(&postService, g)
|
||||
|
||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
router.Run(":8080")
|
||||
}
|
||||
|
|
|
|||
10
config.yaml
10
config.yaml
|
|
@ -1,10 +0,0 @@
|
|||
db-user: userpg
|
||||
db-name: 58blog
|
||||
db-password: 1205
|
||||
db-host: localhost
|
||||
db-port: 5432
|
||||
admin_name: muts
|
||||
admin_pass: 1205
|
||||
images_path: ./images/
|
||||
posts_path: ./posts/
|
||||
|
||||
32
docs/docs.go
32
docs/docs.go
|
|
@ -1,11 +1,35 @@
|
|||
// Code generated by swaggo/swag. DO NOT EDIT.
|
||||
|
||||
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag/v2"
|
||||
import "github.com/swaggo/swag"
|
||||
|
||||
const docTemplate = `{
|
||||
"schemes": {{ marshal .Schemes }},"swagger":"2.0","info":{"description":"{{escape .Description}}","title":"{{.Title}}","termsOfService":"http://swagger.io/terms/","contact":{"name":"API Support","url":"http://www.swagger.io/support","email":"support@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"version":"{{.Version}}"},"host":"{{.Host}}","basePath":"{{.BasePath}}","paths":{"/images/{path}":{"get":{"description":"get image by path","produces":["image/png","image/jpeg"],"summary":"Get an image by path","parameters":[{"type":"string","description":"Path to image","name":"path","in":"query","required":true}],"responses":{"200":{"description":"OK"}}}},"/post":{"get":{"description":"Return first 5 posts","produces":["application/json"],"tags":["post"],"summary":"Get all posts","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}}}},"post":{"description":"Create new post in blog","consumes":["application/json"],"produces":["application/json"],"tags":["post"],"summary":"Create new post","parameters":[{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreatePostRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/{id}":{"get":{"description":"get post by id","produces":["application/json"],"tags":["post"],"summary":"Get post by id","parameters":[{"type":"string","description":"Id of post","name":"id","in":"query","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.PostResponse"}}}}},"put":{"description":"update post content","produces":["application/json"],"tags":["post"],"summary":"Update post content","parameters":[{"type":"string","description":"Id of post","name":"id","in":"query","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}}}}},"/post/{offset}":{"get":{"description":"return 5 posts after first offset posts","produces":["application/json"],"tags":["post"],"summary":"Get posts after offset","parameters":[{"type":"integer","description":"Offset of posts","name":"offset","in":"query","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}}}}}},"definitions":{"requests.CreatePostRequest":{"type":"object","required":["content","description","title","userId"],"properties":{"content":{"type":"string","minLength":36},"description":{"type":"string","maxLength":255,"minLength":8},"title":{"type":"string","maxLength":255,"minLength":8},"userId":{"type":"string"}}},"responses.ErrorResponse":{"type":"object","properties":{"error_code":{"type":"integer"},"message":{"type":"string"}}},"responses.GetListPostResponseItem":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"}}},"responses.PostResponse":{"type":"object","properties":{"content":{"type":"string"},"createdAt":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"}}}},"securityDefinitions":{"BasicAuth":{"type":"basic"}}}`
|
||||
"schemes": {{ marshal .Schemes }},
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "{{escape .Description}}",
|
||||
"title": "{{.Title}}",
|
||||
"termsOfService": "http://swagger.io/terms/",
|
||||
"contact": {
|
||||
"name": "API Support",
|
||||
"url": "http://www.swagger.io/support",
|
||||
"email": "support@swagger.io"
|
||||
},
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
},
|
||||
"version": "{{.Version}}"
|
||||
},
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {},
|
||||
"securityDefinitions": {
|
||||
"BasicAuth": {
|
||||
"type": "basic"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = &swag.Spec{
|
||||
|
|
|
|||
|
|
@ -1 +1,26 @@
|
|||
{"swagger":"2.0","info":{"description":"58team blog's backend","title":"58team blog backend","termsOfService":"http://swagger.io/terms/","contact":{"name":"API Support","url":"http://www.swagger.io/support","email":"support@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"version":"1.0"},"host":"localhost:8080","basePath":"/api/v1","paths":{"/images/{path}":{"get":{"description":"get image by path","produces":["image/png","image/jpeg"],"summary":"Get an image by path","parameters":[{"type":"string","description":"Path to image","name":"path","in":"query","required":true}],"responses":{"200":{"description":"OK"}}}},"/post":{"get":{"description":"Return first 5 posts","produces":["application/json"],"tags":["post"],"summary":"Get all posts","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}}}},"post":{"description":"Create new post in blog","consumes":["application/json"],"produces":["application/json"],"tags":["post"],"summary":"Create new post","parameters":[{"description":"Post data","name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/requests.CreatePostRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/responses.ErrorResponse"}}}}},"/post/{id}":{"get":{"description":"get post by id","produces":["application/json"],"tags":["post"],"summary":"Get post by id","parameters":[{"type":"string","description":"Id of post","name":"id","in":"query","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.PostResponse"}}}}},"put":{"description":"update post content","produces":["application/json"],"tags":["post"],"summary":"Update post content","parameters":[{"type":"string","description":"Id of post","name":"id","in":"query","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/responses.PostResponse"}}}}},"/post/{offset}":{"get":{"description":"return 5 posts after first offset posts","produces":["application/json"],"tags":["post"],"summary":"Get posts after offset","parameters":[{"type":"integer","description":"Offset of posts","name":"offset","in":"query","required":true}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/responses.GetListPostResponseItem"}}}}}}},"definitions":{"requests.CreatePostRequest":{"type":"object","required":["content","description","title","userId"],"properties":{"content":{"type":"string","minLength":36},"description":{"type":"string","maxLength":255,"minLength":8},"title":{"type":"string","maxLength":255,"minLength":8},"userId":{"type":"string"}}},"responses.ErrorResponse":{"type":"object","properties":{"error_code":{"type":"integer"},"message":{"type":"string"}}},"responses.GetListPostResponseItem":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"}}},"responses.PostResponse":{"type":"object","properties":{"content":{"type":"string"},"createdAt":{"type":"string"},"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"}}}},"securityDefinitions":{"BasicAuth":{"type":"basic"}}}
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "58team blog's backend",
|
||||
"title": "58team blog backend",
|
||||
"termsOfService": "http://swagger.io/terms/",
|
||||
"contact": {
|
||||
"name": "API Support",
|
||||
"url": "http://www.swagger.io/support",
|
||||
"email": "support@swagger.io"
|
||||
},
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
},
|
||||
"version": "1.0"
|
||||
},
|
||||
"host": "localhost:8080",
|
||||
"basePath": "/api/v1",
|
||||
"paths": {},
|
||||
"securityDefinitions": {
|
||||
"BasicAuth": {
|
||||
"type": "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +1,4 @@
|
|||
basePath: /api/v1
|
||||
definitions:
|
||||
requests.CreatePostRequest:
|
||||
properties:
|
||||
content:
|
||||
minLength: 36
|
||||
type: string
|
||||
description:
|
||||
maxLength: 255
|
||||
minLength: 8
|
||||
type: string
|
||||
title:
|
||||
maxLength: 255
|
||||
minLength: 8
|
||||
type: string
|
||||
userId:
|
||||
type: string
|
||||
required:
|
||||
- content
|
||||
- description
|
||||
- title
|
||||
- userId
|
||||
type: object
|
||||
responses.ErrorResponse:
|
||||
properties:
|
||||
error_code:
|
||||
type: integer
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
responses.GetListPostResponseItem:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
type: object
|
||||
responses.PostResponse:
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
userId:
|
||||
type: string
|
||||
type: object
|
||||
host: localhost:8080
|
||||
info:
|
||||
contact:
|
||||
|
|
@ -67,123 +12,7 @@ info:
|
|||
termsOfService: http://swagger.io/terms/
|
||||
title: 58team blog backend
|
||||
version: "1.0"
|
||||
paths:
|
||||
/images/{path}:
|
||||
get:
|
||||
description: get image by path
|
||||
parameters:
|
||||
- description: Path to image
|
||||
in: query
|
||||
name: path
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- image/png
|
||||
- image/jpeg
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Get an image by path
|
||||
/post:
|
||||
get:
|
||||
description: Return first 5 posts
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/responses.GetListPostResponseItem'
|
||||
type: array
|
||||
summary: Get all posts
|
||||
tags:
|
||||
- post
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Create new post in blog
|
||||
parameters:
|
||||
- description: Post data
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.CreatePostRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/responses.PostResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/responses.ErrorResponse'
|
||||
summary: Create new post
|
||||
tags:
|
||||
- post
|
||||
/post/{id}:
|
||||
get:
|
||||
description: get post by id
|
||||
parameters:
|
||||
- description: Id of post
|
||||
in: query
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/responses.PostResponse'
|
||||
type: array
|
||||
summary: Get post by id
|
||||
tags:
|
||||
- post
|
||||
put:
|
||||
description: update post content
|
||||
parameters:
|
||||
- description: Id of post
|
||||
in: query
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/responses.PostResponse'
|
||||
summary: Update post content
|
||||
tags:
|
||||
- post
|
||||
/post/{offset}:
|
||||
get:
|
||||
description: return 5 posts after first offset posts
|
||||
parameters:
|
||||
- description: Offset of posts
|
||||
in: query
|
||||
name: offset
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/responses.GetListPostResponseItem'
|
||||
type: array
|
||||
summary: Get posts after offset
|
||||
tags:
|
||||
- post
|
||||
paths: {}
|
||||
securityDefinitions:
|
||||
BasicAuth:
|
||||
type: basic
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 60 KiB |
14
go.mod
14
go.mod
|
|
@ -16,13 +16,12 @@ require (
|
|||
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.10.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/spec v0.20.9 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator v9.31.0+incompatible // indirect
|
||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
|
|
@ -34,12 +33,11 @@ require (
|
|||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
|
|
@ -47,11 +45,9 @@ require (
|
|||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/sv-tools/openapi v0.2.1 // indirect
|
||||
github.com/swaggo/files v1.0.1 // indirect
|
||||
github.com/swaggo/gin-swagger v1.6.1 // indirect
|
||||
github.com/swaggo/swag v1.16.6 // indirect
|
||||
github.com/swaggo/swag/v2 v2.0.0-rc4 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
|
|
|
|||
21
go.sum
21
go.sum
|
|
@ -31,28 +31,17 @@ github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T
|
|||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
|
||||
github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
|
||||
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
|
||||
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
|
|
@ -76,7 +65,6 @@ github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzh
|
|||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
|
|
@ -88,8 +76,6 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
|
|||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
|
|
@ -101,8 +87,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
|
|||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
|
|
@ -127,8 +111,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
|||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/sv-tools/openapi v0.2.1 h1:ES1tMQMJFGibWndMagvdoo34T1Vllxr1Nlm5wz6b1aA=
|
||||
github.com/sv-tools/openapi v0.2.1/go.mod h1:k5VuZamTw1HuiS9p2Wl5YIDWzYnHG6/FgPOSFXLAhGg=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||
github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs7cY=
|
||||
|
|
@ -137,8 +119,6 @@ github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
|
|||
github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
|
||||
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
|
||||
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
|
||||
github.com/swaggo/swag/v2 v2.0.0-rc4 h1:SZ8cK68gcV6cslwrJMIOqPkJELRwq4gmjvk77MrvHvY=
|
||||
github.com/swaggo/swag/v2 v2.0.0-rc4/go.mod h1:Ow7Y8gF16BTCDn8YxZbyKn8FkMLRUHekv1kROJZpbvE=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||
|
|
@ -197,7 +177,6 @@ google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXn
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
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=
|
||||
|
|
|
|||
|
|
@ -7,17 +7,18 @@ import (
|
|||
"58team_blog/internal/application/queries"
|
||||
"58team_blog/internal/domain/entities"
|
||||
"58team_blog/internal/domain/repository"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PostService struct {
|
||||
repo repository.PostRepository
|
||||
repo repository.PostRepository
|
||||
postsService PostsService
|
||||
}
|
||||
|
||||
func CreatePostService(repo repository.PostRepository) PostService {
|
||||
func CreatePostService(repo repository.PostRepository, postsService PostsService) PostService {
|
||||
return PostService{
|
||||
repo: repo,
|
||||
repo: repo,
|
||||
postsService: postsService,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ func (s *PostService) Create(cmd commands.CreatePostCommand) (*common.PostResult
|
|||
|
||||
post, err := s.repo.Create(&entity)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Db error: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := mapper.CreatePostResultFromEntity(post)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ const PostTable = "post"
|
|||
|
||||
type Post struct {
|
||||
Id uuid.UUID `db:"id"`
|
||||
UserId uuid.UUID `db:"userid"`
|
||||
UserId uuid.UUID `db:"user_id"`
|
||||
Title string `db:"title"`
|
||||
Description string `db:"description"`
|
||||
Content string `db:"content"`
|
||||
CreatedAt time.Time `db:"createdat"`
|
||||
UpdatedAt time.Time `db:"updatedat"`
|
||||
CreatedAt time.Time `db:"createdAt"`
|
||||
UpdatedAt time.Time `db:"updatedAt"`
|
||||
}
|
||||
|
||||
func CreatePost(userId uuid.UUID, title string, description string, content string) (post Post, err error) {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ type Config struct {
|
|||
PostsPath string `mapstructure:"posts_path" default:"./posts/"`
|
||||
}
|
||||
|
||||
func LoadConfig() (config *Config, err error) {
|
||||
config = &Config{}
|
||||
func LoadConfig() (config Config, err error) {
|
||||
config = Config{}
|
||||
if err = defaults.Set(config); err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
viper.SetConfigName("config")
|
||||
|
|
@ -30,12 +30,12 @@ func LoadConfig() (config *Config, err error) {
|
|||
viper.AddConfigPath("/58team_blog/cfgs/")
|
||||
|
||||
if err = viper.ReadInConfig(); err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
if err = viper.Unmarshal(&config); err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
return config, nil
|
||||
return
|
||||
}
|
||||
|
|
|
|||
19
internal/infrastructure/db.go
Normal file
19
internal/infrastructure/db.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package infrastructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
connection *sqlx.DB
|
||||
}
|
||||
|
||||
func DatabaseInit(config Config) (db Database, err error) {
|
||||
db = Database{}
|
||||
db_setup := fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s", config.DBUser, config.DBPass, config.DBHost, config.DBPort, config.DBName)
|
||||
db.connection, err = sqlx.Connect("postgres", db_setup)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"58team_blog/internal/infrastructure"
|
||||
"fmt"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
Conn *sqlx.DB
|
||||
}
|
||||
|
||||
func DatabaseInit(config infrastructure.Config) (db *Database, err error) {
|
||||
db = &Database{}
|
||||
|
||||
db_setup := fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=disable", config.DBUser, config.DBPass, config.DBHost, config.DBPort, config.DBName)
|
||||
db.Conn, err = sqlx.Connect("postgres", db_setup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"58team_blog/internal/domain/entities"
|
||||
"58team_blog/internal/infrastructure/db"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type ImagesRepository struct {
|
||||
conn *db.Database
|
||||
}
|
||||
|
||||
func CreateImagesRepository(conn *db.Database) ImagesRepository {
|
||||
return ImagesRepository{
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ImagesRepository) Create(entity *entities.Images) error {
|
||||
query := "INSERT INTO " + entities.ImagesTable + "(id, path) VALUES (:id, :path)"
|
||||
_, err := r.conn.Conn.NamedExec(query, entity)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *ImagesRepository) FindById(id uuid.UUID) (*entities.Images, error) {
|
||||
var entity *entities.Images
|
||||
|
||||
query := "SELECT * FROM " + entities.ImagesTable + " WHERE id = ?"
|
||||
query, args, err := sqlx.In(query, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
err = r.conn.Conn.Get(entity, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
func (r *ImagesRepository) Delete(id uuid.UUID) error {
|
||||
query := "DELETE FROM " + entities.ImagesTable + " WHERE id=?"
|
||||
|
||||
query, args, err := sqlx.In(query, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
_, err = r.conn.Conn.Query(query, args...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"58team_blog/internal/domain/entities"
|
||||
"58team_blog/internal/infrastructure/db"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type PostRepository struct {
|
||||
conn *db.Database
|
||||
}
|
||||
|
||||
func CreatePostRepository(conn *db.Database) PostRepository {
|
||||
return PostRepository{
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *PostRepository) Create(entity *entities.Post) (*entities.Post, error) {
|
||||
query := "INSERT INTO " + entities.PostTable + " (id, userid, title, description, content, createdat, updatedat)" +
|
||||
"VALUES (:id, :userid, :title, :description, :content, :createdat, :updatedat)"
|
||||
_, err := r.conn.Conn.NamedExec(query, entity)
|
||||
|
||||
return entity, err
|
||||
}
|
||||
|
||||
func (r *PostRepository) FindById(id uuid.UUID) (*entities.Post, error) {
|
||||
var entity *entities.Post
|
||||
query := "SELECT * FROM " + entities.PostTable + " WHERE id=?"
|
||||
|
||||
query, args, err := sqlx.In(query, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
err = r.conn.Conn.Get(entity, query, args)
|
||||
|
||||
return entity, err
|
||||
}
|
||||
|
||||
func (r *PostRepository) FindAllByUserName(userName string) ([]*entities.Post, error) {
|
||||
var entity_list []*entities.Post
|
||||
query := "SELECT * FROM " + entities.PostTable + " WHERE userid=?"
|
||||
|
||||
query, args, err := sqlx.In(query, userName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
err = r.conn.Conn.Select(entity_list, query, args...)
|
||||
|
||||
return entity_list, err
|
||||
}
|
||||
|
||||
func (r *PostRepository) GetAll() ([]*entities.Post, error) {
|
||||
var entity_list []*entities.Post
|
||||
query := "SELECT * FROM " + entities.PostTable + " ORDER BY createdat, updatedat LIMIT 5;"
|
||||
|
||||
err := r.conn.Conn.Select(&entity_list, query)
|
||||
|
||||
return entity_list, err
|
||||
}
|
||||
|
||||
func (r *PostRepository) Update(entity *entities.Post) error {
|
||||
query := "UPDATE " + entities.PostTable + "SET title=:title, description=:description, content=:content, updatedat=:updatedat WHERE id=:id"
|
||||
|
||||
_, err := r.conn.Conn.NamedExec(query, entity)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PostRepository) Delete(id uuid.UUID) error {
|
||||
query := "DELETE FROM " + entities.PostTable + " WHERE id=?"
|
||||
|
||||
query, args, err := sqlx.In(query, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
_, err = r.conn.Conn.Exec(query, args...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"58team_blog/internal/domain/entities"
|
||||
"58team_blog/internal/infrastructure/db"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type UserRepository struct {
|
||||
conn *db.Database
|
||||
}
|
||||
|
||||
func CreateUserRepository(conn *db.Database) UserRepository {
|
||||
return UserRepository{
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *UserRepository) Create(entity *entities.User) (*entities.User, error) {
|
||||
query := "INSERT INTO " + entities.UserTable + "(id, username, password) VALUES (:id, :username, :password)"
|
||||
_, err := r.conn.Conn.NamedExec(query, entity)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
func (r *UserRepository) FindById(id uuid.UUID) (*entities.User, error) {
|
||||
var entity *entities.User
|
||||
|
||||
query := "SELECT * FROM " + entities.UserTable + " WHERE id=?"
|
||||
query, arg, err := sqlx.In(query, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
err = r.conn.Conn.Get(entity, query, arg...)
|
||||
|
||||
return entity, err
|
||||
}
|
||||
|
||||
func (r *UserRepository) FindByName(username string) (*entities.User, error) {
|
||||
var entity *entities.User
|
||||
|
||||
query := "SELECT * FROM " + entities.UserTable + " WHERE username=?"
|
||||
query, arg, err := sqlx.In(query, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
err = r.conn.Conn.Get(entity, query, arg...)
|
||||
|
||||
return entity, err
|
||||
}
|
||||
|
||||
func (r *UserRepository) GetAll() ([]*entities.User, error) {
|
||||
var entity_list []*entities.User
|
||||
|
||||
query := "SELECT * FROM " + entities.UserTable
|
||||
err := r.conn.Conn.Select(entity_list, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entity_list, nil
|
||||
}
|
||||
|
||||
func (r *UserRepository) Update(user *entities.User) error {
|
||||
query := "UPDATE " + entities.UserTable + " SET username=:username, password=:password WHERE id=:id"
|
||||
|
||||
_, err := r.conn.Conn.NamedExec(query, user)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *UserRepository) Delete(id uuid.UUID) error {
|
||||
query := "DELETE FROM " + entities.UserTable + " WHERE id=?"
|
||||
|
||||
query, arg, err := sqlx.In(query, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query = r.conn.Conn.Rebind(query)
|
||||
_, err = r.conn.Conn.Exec(query, arg...)
|
||||
|
||||
return err
|
||||
}
|
||||
20
internal/infrastructure/infrastructure.go
Normal file
20
internal/infrastructure/infrastructure.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package infrastructure
|
||||
|
||||
type Infrastructure struct {
|
||||
Config Config
|
||||
Db Database
|
||||
}
|
||||
|
||||
func InfrastructureInit() (infra Infrastructure, err error) {
|
||||
infra = Infrastructure{}
|
||||
|
||||
if infra.Config, err = LoadConfig(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if infra.Db, err = DatabaseInit(infra.Config); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ImagesController struct {
|
||||
service *services.ImagesService
|
||||
}
|
||||
|
||||
func CreateImagesController(service *services.ImagesService) ImagesController {
|
||||
return ImagesController{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// get /images/{path}
|
||||
// post /images
|
||||
// delete /images/{id}
|
||||
|
||||
// @Summary Get an image by path
|
||||
// @Description get image by path
|
||||
// @Param path query string true "Path to image"
|
||||
// @Produce image/png
|
||||
// @Produce image/jpeg
|
||||
// @Success 200
|
||||
// @Router /images/{path} [get]
|
||||
func (r *ImagesController) GetImage(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (r *ImagesController) PostImage(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (r *ImagesController) DeleteImage(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/commands"
|
||||
"58team_blog/internal/application/queries"
|
||||
"58team_blog/internal/application/services"
|
||||
"58team_blog/internal/interfaces/api/dto"
|
||||
"58team_blog/internal/interfaces/api/requests"
|
||||
"58team_blog/internal/interfaces/api/responses"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type PostController struct {
|
||||
service *services.PostService
|
||||
}
|
||||
|
||||
func CreatePostController(service *services.PostService) PostController {
|
||||
return PostController{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// PostPost godoc
|
||||
//
|
||||
// @Summary Create new post
|
||||
// @Description Create new post in blog
|
||||
// @Tags post
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body requests.CreatePostRequest true "Post data"
|
||||
// @Success 200 {object} responses.PostResponse
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /post [post]
|
||||
func (r *PostController) Post(c *gin.Context) {
|
||||
var request requests.CreatePostRequest
|
||||
|
||||
if err := c.BindJSON(&request); err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusBadRequest, "BadRequest")
|
||||
c.IndentedJSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
userId, err := uuid.Parse(request.UserId)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Incorrect user id")
|
||||
c.IndentedJSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
cmd := commands.CreatePostCommand{
|
||||
UserId: userId,
|
||||
Title: request.Title,
|
||||
Description: request.Description,
|
||||
Content: request.Content,
|
||||
}
|
||||
|
||||
res, err := r.service.Create(cmd)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
|
||||
c.IndentedJSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
response := dto.ResponseFromPostResult(res)
|
||||
|
||||
c.IndentedJSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// GetAllPost godoc
|
||||
//
|
||||
// @Summary Get all posts
|
||||
// @Description Return first 5 posts
|
||||
// @Tags post
|
||||
// @Produce json
|
||||
// @Success 200 {array} responses.GetListPostResponseItem
|
||||
// @Failure 500 {object} responses.ErrorResponse
|
||||
// @Router /post [get]
|
||||
func (r *PostController) GetAll(c *gin.Context) {
|
||||
result, err := r.service.GetAll()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
resp := responses.CreateErrorResponse(http.StatusInternalServerError, "Internal server error")
|
||||
c.IndentedJSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
res := dto.ResponseFromPostGetAllResult(result)
|
||||
|
||||
c.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
// GetAllWithOffsetPost godoc
|
||||
// @Summary Get posts after offset
|
||||
// @Description return 5 posts after first offset posts
|
||||
// @Tags post
|
||||
// @Param offset query int true "Offset of posts"
|
||||
// @Produce json
|
||||
// @Success 200 {array} responses.GetListPostResponseItem
|
||||
// @Router /post/{offset} [get]
|
||||
func (r *PostController) GetAllWithOffset(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
// GetByIdPost godoc
|
||||
// @Summary Get post by id
|
||||
// @Description get post by id
|
||||
// @Tags post
|
||||
// @Param id query string true "Id of post"
|
||||
// @Produce json
|
||||
// @Success 200 {array} responses.PostResponse
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Router /post/{id} [get]
|
||||
func (r *PostController) GetById(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
id_valid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Println("User get by id error: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Invalid user id")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
query := queries.PostFindByIdQuery{
|
||||
Id: id_valid,
|
||||
}
|
||||
|
||||
posts, err := r.service.FindById(query)
|
||||
if err != nil {
|
||||
log.Println("Post service error: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
return
|
||||
}
|
||||
|
||||
result := dto.ResponseFormPostFindByIdResult(posts)
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// PutPost godoc
|
||||
// @Summary Update post content
|
||||
// @Description update post content
|
||||
// @Tags post
|
||||
// @Param id query string true "Id of post"
|
||||
//
|
||||
// @Param request body requests.PutPostRequest true "Post data"
|
||||
//
|
||||
// @Produce json
|
||||
// @Success 200 {object} responses.PostResponse
|
||||
// @Failure 400 {object} responses.ErrorResponse
|
||||
// @Router /post/{id} [put]
|
||||
func (r *PostController) Put(c *gin.Context) {
|
||||
var request requests.PutPostRequest
|
||||
|
||||
if err := c.BindJSON(request); err != nil {
|
||||
log.Println("Post request error: ", err)
|
||||
resp := responses.CreateErrorResponse(http.StatusBadRequest, "Bad request")
|
||||
c.JSON(resp.ErrorCode, resp)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete godoc
|
||||
// @Summary Delete post
|
||||
// @Description Delete post by id
|
||||
// @Tags post
|
||||
// @Param id query string true "Id of post"
|
||||
// @Produce json
|
||||
// @Success 200
|
||||
// @Router /post/{id} [delete]
|
||||
|
||||
func (r *PostController) Delete(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
service *services.UserService
|
||||
}
|
||||
|
||||
func CreateUserController(service *services.UserService) UserController {
|
||||
return UserController{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// @Summary Create new user
|
||||
// @Description Creates new user in system
|
||||
// @Param path query string true "Path to image"
|
||||
// @Produce
|
||||
// @Success 200
|
||||
// @Router /images/{path} [get]
|
||||
func (r *UserController) Post(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (r *UserController) FindById(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
func (r *UserController) FindByName(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
func (r *UserController) GetAll(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (r *UserController) Put(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
func (r *UserController) Delete(c *gin.Context) {
|
||||
// TODO: return image
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/queries"
|
||||
"58team_blog/internal/interfaces/api/responses"
|
||||
)
|
||||
|
||||
func ResponseFormPostFindByIdResult(result *queries.PostFindByIdResult) responses.PostResponse {
|
||||
res := result.Result
|
||||
return responses.PostResponse{
|
||||
Id: res.Id.String(),
|
||||
UserId: res.UserId.String(),
|
||||
Title: res.Title,
|
||||
Description: res.Description,
|
||||
Content: res.Content,
|
||||
CreatedAt: res.CreatedAt,
|
||||
UpdatedAt: res.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/common"
|
||||
"58team_blog/internal/application/queries"
|
||||
"58team_blog/internal/interfaces/api/responses"
|
||||
)
|
||||
|
||||
func itemFromResult(item *common.PostResult) responses.GetListPostResponseItem {
|
||||
return responses.GetListPostResponseItem{
|
||||
Id: item.Id.String(),
|
||||
Title: item.Title,
|
||||
Description: item.Description,
|
||||
}
|
||||
}
|
||||
|
||||
func ResponseFromPostGetAllResult(result *queries.PostGetAllResult) responses.GetListPostResponse {
|
||||
var resp []responses.GetListPostResponseItem
|
||||
|
||||
for _, r := range result.Result.Result {
|
||||
resp = append(resp, itemFromResult(r))
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/common"
|
||||
"58team_blog/internal/interfaces/api/responses"
|
||||
)
|
||||
|
||||
func ResponseFromPostResult(result *common.PostResult) responses.PostResponse {
|
||||
return responses.PostResponse{
|
||||
Id: result.Id.String(),
|
||||
UserId: result.UserId.String(),
|
||||
Title: result.Title,
|
||||
Description: result.Description,
|
||||
Content: result.Content,
|
||||
CreatedAt: result.CreatedAt,
|
||||
UpdatedAt: result.UpdatedAt,
|
||||
}
|
||||
}
|
||||
1
internal/interfaces/api/images_controller.go
Normal file
1
internal/interfaces/api/images_controller.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package api
|
||||
1
internal/interfaces/api/post_controller.go
Normal file
1
internal/interfaces/api/post_controller.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package api
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package requests
|
||||
|
||||
type CreatePostRequest struct {
|
||||
Title string `json:"title" validate:"required,min=8,max=255"`
|
||||
Description string `json:"description" validate:"required,min=8,max=255"`
|
||||
Content string `json:"content" validate:"required,min=36"`
|
||||
UserId string `json:"userId" validate:"required,uuid5"`
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
package requests
|
||||
|
||||
type PutPostRequest struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package responses
|
||||
|
||||
type ErrorResponse struct {
|
||||
ErrorCode int `json:"error_code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func CreateErrorResponse(code int, msg string) ErrorResponse {
|
||||
return ErrorResponse{
|
||||
ErrorCode: code,
|
||||
Message: msg,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package responses
|
||||
|
||||
type GetListPostResponseItem struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type GetListPostResponse []GetListPostResponseItem
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package responses
|
||||
|
||||
import "time"
|
||||
|
||||
type PostResponse struct {
|
||||
Id string `json:"id"`
|
||||
UserId string `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type PostResponseList []*PostResponse
|
||||
1
internal/interfaces/api/user_controller.go
Normal file
1
internal/interfaces/api/user_controller.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package api
|
||||
|
|
@ -1,18 +1 @@
|
|||
package interfaces
|
||||
|
||||
import (
|
||||
"58team_blog/internal/application/services"
|
||||
"58team_blog/internal/interfaces/api/controllers"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func BindPostAdmin(service *services.PostService, group *gin.RouterGroup) {
|
||||
post := controllers.CreatePostController(service)
|
||||
|
||||
g := group.Group("/post")
|
||||
g.GET("/", post.GetAllPost)
|
||||
g.GET("/:id", post.GetByIdPost)
|
||||
g.POST("/", post.PostPost)
|
||||
g.PUT("/:id", post.PutPost)
|
||||
}
|
||||
|
|
|
|||
BIN
migrate
BIN
migrate
Binary file not shown.
98
migrate.go
98
migrate.go
|
|
@ -1,98 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"58team_blog/internal/infrastructure"
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var command = flag.String("command", "up", "Migration command: up, down, version, force.")
|
||||
var steps = flag.Int("steps", -1, "Number of migration steps (for up/down commands)")
|
||||
var version = flag.Int("version", -1, "Target version (for force command)")
|
||||
|
||||
config, err := infrastructure.LoadConfig()
|
||||
if err != nil {
|
||||
log.Fatal("Cannot load config file: ", err)
|
||||
}
|
||||
|
||||
DbUrl := "postgres://" + config.DBUser + ":" + config.DBPass +
|
||||
"@" + config.DBHost + ":" + config.DBPort + "/" + config.DBName + "?sslmode=disable"
|
||||
fmt.Println(DbUrl)
|
||||
|
||||
db, err := sql.Open("postgres", DbUrl)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to connect to database:", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
driver, err := postgres.WithInstance(db, &postgres.Config{})
|
||||
if err != nil {
|
||||
log.Fatal("Failed to create database driver:", err)
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithDatabaseInstance("file://./migrations", "postgres", driver)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to create migrate instance:", err)
|
||||
}
|
||||
defer m.Close()
|
||||
|
||||
switch *command {
|
||||
case "up":
|
||||
if *steps > 0 {
|
||||
err = m.Steps(*steps)
|
||||
} else {
|
||||
err = m.Up()
|
||||
}
|
||||
if err != nil && err != migrate.ErrNoChange {
|
||||
log.Fatal("Migration up failed:", err)
|
||||
}
|
||||
if err == migrate.ErrNoChange {
|
||||
fmt.Println("No migrations to apply")
|
||||
} else {
|
||||
fmt.Println("Migrations applied successfully")
|
||||
}
|
||||
|
||||
case "down":
|
||||
if *steps > 0 {
|
||||
err = m.Steps(-*steps)
|
||||
} else {
|
||||
err = m.Down()
|
||||
}
|
||||
if err != nil && err != migrate.ErrNoChange {
|
||||
log.Fatal("Migration down failed:", err)
|
||||
}
|
||||
if err == migrate.ErrNoChange {
|
||||
fmt.Println("No migrations to rollback")
|
||||
} else {
|
||||
fmt.Println("Migrations rolled back successfully")
|
||||
}
|
||||
|
||||
case "version":
|
||||
version, dirty, err := m.Version()
|
||||
if err != nil {
|
||||
log.Fatal("Failed to get version:", err)
|
||||
}
|
||||
fmt.Printf("Current version: %d (dirty: %v)\n", version, dirty)
|
||||
|
||||
case "force":
|
||||
if *version < 0 {
|
||||
log.Fatal("Version is required for force command. Use -version flag")
|
||||
}
|
||||
err = m.Force(*version)
|
||||
if err != nil {
|
||||
log.Fatal("Force migration failed:", err)
|
||||
}
|
||||
fmt.Printf("Forced migration to version %d\n", *version)
|
||||
|
||||
default:
|
||||
log.Fatal("Unknown command:", *command)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
DROP TABLE IF EXISTS images;
|
||||
DROP TABLE IF EXISTS users;
|
||||
DROP TABLE IF EXISTS post;
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS post (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
createdAt TIMESTAMP NOT NULL,
|
||||
updatedAt TIMESTAMP NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS images (
|
||||
id TEXT PRIMARY KEY,
|
||||
path TEXT NOT NULL
|
||||
);
|
||||
47
migrations/create.sql
Normal file
47
migrations/create.sql
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
CREATE TABLE "users" (
|
||||
"id" TEXT NOT NULL UNIQUE,
|
||||
"username" VARCHAR(255) UNIQUE,
|
||||
"password" VARCHAR(255),
|
||||
PRIMARY KEY("id")
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
CREATE TABLE "post" (
|
||||
"id" TEXT NOT NULL UNIQUE,
|
||||
"title" TEXT,
|
||||
"description" TEXT,
|
||||
"content" TEXT,
|
||||
"createdAt" TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP,
|
||||
PRIMARY KEY("id")
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
CREATE TABLE "posts" (
|
||||
"id" TEXT NOT NULL UNIQUE,
|
||||
"user_id" INTEGER,
|
||||
"post_id" INTEGER,
|
||||
PRIMARY KEY("id")
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
CREATE TABLE "images" (
|
||||
"id" TEXT NOT NULL UNIQUE,
|
||||
"path" TEXT,
|
||||
PRIMARY KEY("id")
|
||||
);
|
||||
|
||||
|
||||
|
||||
ALTER TABLE "users"
|
||||
ADD FOREIGN KEY("id") REFERENCES "posts"("user_id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
ALTER TABLE "post"
|
||||
ADD FOREIGN KEY("id") REFERENCES "posts"("post_id")
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION;
|
||||
Loading…
Add table
Add a link
Reference in a new issue