This commit is contained in:
fallen-angle
2022-05-16 19:55:59 +08:00
parent 7598280fc1
commit 9e3638885d
34 changed files with 3623 additions and 115 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,9 @@ definitions:
createUser: createUser:
description: 文章创建者id description: 文章创建者id
type: integer type: integer
id:
description: 文章id
type: integer
isDelete: isDelete:
description: 删除标志 description: 删除标志
type: integer type: integer
@@ -76,6 +79,138 @@ definitions:
description: 文章标题 description: 文章标题
type: string type: string
type: object type: object
models.BackLocation:
properties:
address:
description: 地点的精确地址
type: string
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
id:
description: ID
type: integer
isDelete:
description: 删除标志
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 地点名
type: string
principalName:
description: 负责人姓名
type: string
principalPhone:
description: 负责人电话
type: string
region:
description: 地点所在地区
type: string
type: object
models.BackNotification:
properties:
content:
type: string
kind:
type: string
time:
type: string
type: object
models.BackObservation:
properties:
address:
description: 受观察者所在具体地点
type: string
age:
description: 年龄
type: integer
contactPerson:
description: 接触者id
type: integer
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
healthChangeTime:
description: 患者健康状况转化时间
type: string
healthSituation:
description: 被观察者的疫情状况0- 其他1-患者2-密接3-次密接
type: integer
id:
description: ID
type: integer
identification:
description: 身份证号
type: string
isDelete:
description: 删除标志
type: integer
measureSituation:
description: 受观察者被采取措施状况 0-未采取措施1-解除风险2-正在治疗3-集中隔离4-居家隔离
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 姓名
type: string
phone:
description: 手机号码
type: string
region:
description: 受观察者所在区域
type: string
sex:
description: 性别
type: integer
trajectory:
description: 行程轨迹
type: string
type: object
models.BackPcr:
properties:
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
detectResult:
description: 核酸检测结果0-未检测1-阴性2-阳性
type: integer
detectTime:
description: 核酸检测时间
type: string
id:
description: ID
type: integer
isDelete:
description: 删除标志
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
observation:
description: 观察对象ID
type: integer
type: object
models.BackUser: models.BackUser:
properties: properties:
approver: approver:
@@ -256,6 +391,8 @@ definitions:
type: string type: string
createTime: createTime:
type: string type: string
id:
type: integer
modifyTime: modifyTime:
type: string type: string
resume: resume:
@@ -267,6 +404,129 @@ definitions:
username: username:
type: string type: string
type: object type: object
models.ListObservation:
properties:
address:
description: 受观察者所在具体地点
type: string
age:
description: 年龄
type: integer
contactPerson:
description: 接触者id
type: integer
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
healthChangeTime:
description: 患者健康状况转化时间
type: string
healthSituation:
description: 被观察者的疫情状况0- 其他1-患者2-密接3-次密接
type: integer
id:
type: integer
identification:
description: 身份证号
type: string
measureSituation:
description: 受观察者被采取措施状况 0-未采取措施1-解除风险2-正在治疗3-集中隔离4-居家隔离
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 姓名
type: string
pcrResult:
description: 核酸结果0-未检测1-阴性2-阳性
type: integer
pcrTime:
description: 核酸时间
type: string
phone:
description: 手机号码
type: string
record:
description: 状态转换内容
type: string
recordTime:
description: 状态转换时间
type: string
region:
description: 受观察者所在区域
type: string
sex:
description: 性别
type: integer
trajectory:
description: 行程轨迹
type: string
type: object
models.TreeObservation:
properties:
address:
description: 受观察者所在具体地点
type: string
age:
description: 年龄
type: integer
children:
description: 子结点
items:
$ref: '#/definitions/models.TreeObservation'
type: array
contactPerson:
description: 接触者id
type: integer
createTime:
description: 创建时间
type: string
createUser:
description: 创建者
type: integer
healthChangeTime:
description: 患者健康状况转化时间
type: string
healthSituation:
description: 被观察者的疫情状况0- 其他1-患者2-密接3-次密接
type: integer
id:
type: integer
identification:
description: 身份证号
type: string
measureSituation:
description: 受观察者被采取措施状况 0-未采取措施1-解除风险2-正在治疗3-集中隔离4-居家隔离
type: integer
modifyTime:
description: 修改时间
type: string
modifyUser:
description: 修改者
type: integer
name:
description: 姓名
type: string
phone:
description: 手机号码
type: string
region:
description: 受观察者所在区域
type: string
sex:
description: 性别
type: integer
trajectory:
description: 行程轨迹
type: string
type: object
models.UserApprove: models.UserApprove:
properties: properties:
email: email:
@@ -480,6 +740,456 @@ paths:
summary: get user's articles summary: get user's articles
tags: tags:
- Article - Article
/management/faker/{patientId}:
get:
parameters:
- description: Token
in: header
name: Token
required: true
type: string
- description: Patient Id
in: path
name: patientId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: pull contact from faker
tags:
- Management
/management/location/:
get:
parameters:
- description: 地点的精确地址
in: query
name: address
type: string
- description: 创建时间
in: query
name: createTime
type: string
- description: 创建者
in: query
name: createUser
type: integer
- description: ID
in: query
name: id
type: integer
- description: 删除标志
in: query
name: isDelete
type: integer
- description: 修改时间
in: query
name: modifyTime
type: string
- description: 修改者
in: query
name: modifyUser
type: integer
- description: 地点名
in: query
name: name
type: string
- description: 负责人姓名
in: query
name: principalName
type: string
- description: 负责人电话
in: query
name: principalPhone
type: string
- description: 地点所在地区
in: query
name: region
type: string
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
$ref: '#/definitions/models.BackLocation'
type: object
summary: list locations
tags:
- Management
post:
consumes:
- application/json
parameters:
- description: location
in: body
name: Location
required: true
schema:
$ref: '#/definitions/models.BackLocation'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: insert location
tags:
- Management
/management/location/{id}:
delete:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: Id
in: path
name: Id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: delete location
tags:
- Management
/management/observation/:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: 受观察者所在具体地点
in: query
name: address
type: string
- description: 年龄
in: query
name: age
type: integer
- description: 接触者id
in: query
name: contactPerson
type: integer
- description: 创建时间
in: query
name: createTime
type: string
- description: 创建者
in: query
name: createUser
type: integer
- description: 患者健康状况转化时间
in: query
name: healthChangeTime
type: string
- description: 被观察者的疫情状况0- 其他1-患者2-密接3-次密接
in: query
name: healthSituation
type: integer
- description: ID
in: query
name: id
type: integer
- description: 身份证号
in: query
name: identification
type: string
- description: 删除标志
in: query
name: isDelete
type: integer
- description: 受观察者被采取措施状况 0-未采取措施1-解除风险2-正在治疗3-集中隔离4-居家隔离
in: query
name: measureSituation
type: integer
- description: 修改时间
in: query
name: modifyTime
type: string
- description: 修改者
in: query
name: modifyUser
type: integer
- description: 姓名
in: query
name: name
type: string
- description: 手机号码
in: query
name: phone
type: string
- description: 受观察者所在区域
in: query
name: region
type: string
- description: 性别
in: query
name: sex
type: integer
- description: 行程轨迹
in: query
name: trajectory
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
items:
$ref: '#/definitions/models.ListObservation'
type: array
type: object
summary: list observations by query
tags:
- Management
post:
consumes:
- application/json
parameters:
- description: observation
in: body
name: Observation
required: true
schema:
$ref: '#/definitions/models.BackObservation'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: insert observation
tags:
- Management
put:
consumes:
- application/json
parameters:
- description: observation
in: body
name: Observation
required: true
schema:
$ref: '#/definitions/models.BackObservation'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: update observation
tags:
- Management
/management/observation/{id}:
get:
parameters:
- description: token
in: header
name: token
required: true
type: string
- description: id
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
$ref: '#/definitions/models.BackObservation'
type: object
summary: get observation's info
tags:
- Management
/management/observation/tree/{id}/{direction}:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: id
in: path
name: id
required: true
type: integer
- description: direction
enum:
- up
- down
- all
in: path
name: direction
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
$ref: '#/definitions/models.TreeObservation'
type: object
summary: get transform chain by user
tags:
- Management
/management/pcr/:
post:
parameters:
- description: Pcr
in: body
name: Pcr
required: true
schema:
$ref: '#/definitions/models.BackPcr'
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: insert pcr record
tags:
- Management
/notify/{index}:
delete:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: index
in: path
name: index
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: delete the notify by index, if -1 delete all
tags:
- Notification
/notify/{start}/{end}:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
- description: start
in: path
name: start
required: true
type: integer
- description: end
in: path
name: end
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/utils.GinResponse'
- properties:
data:
items:
$ref: '#/definitions/models.BackNotification'
type: array
type: object
summary: list the notification in the range
tags:
- Notification
/notify/count/:
get:
parameters:
- description: token
in: header
name: Token
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/utils.GinResponse'
summary: count the notification
tags:
- Notification
/statistics/china: /statistics/china:
get: get:
produces: produces:

View File

@@ -12,6 +12,7 @@ type ServerConfig struct {
Jwt JwtConfig `yaml:"jwt"` Jwt JwtConfig `yaml:"jwt"`
Email EmailConfig `yaml:"email"` Email EmailConfig `yaml:"email"`
Bos BosConfig `yaml:"bos"` Bos BosConfig `yaml:"bos"`
Kafka KafkaCofig `yaml:"kafka"`
} }
type MySQLConfig struct { type MySQLConfig struct {
@@ -46,3 +47,9 @@ type BosConfig struct {
SecretKey string `yaml:"secretKey"` SecretKey string `yaml:"secretKey"`
Domain string `yaml:"domain"` Domain string `yaml:"domain"`
} }
type KafkaCofig struct {
Servers []string `yaml:"servers"`
Topic string `yaml:"topic"`
Partition int `yaml:"partition"`
}

View File

@@ -4,12 +4,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/baidubce/bce-sdk-go/services/bos" "github.com/baidubce/bce-sdk-go/services/bos"
"net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-redis/redis" "github.com/go-redis/redis"
"go.uber.org/zap" "go.uber.org/zap"
"gorm.io/gorm" "gorm.io/gorm"
"net/http"
) )
var ( var (
@@ -76,4 +75,5 @@ var (
"NEGATIVE": 1, "NEGATIVE": 1,
"POSITIVE": 2, "POSITIVE": 2,
} }
KafkaProducerChan = make(chan []byte)
) )

19
go.mod
View File

@@ -18,7 +18,12 @@ require (
github.com/KyleBanks/depth v1.2.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/Shopify/sarama v1.32.0 // indirect
github.com/baidubce/bce-sdk-go v0.9.112 // indirect github.com/baidubce/bce-sdk-go v0.9.112 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/eapache/go-resiliency v1.2.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect
@@ -31,13 +36,21 @@ require (
github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect github.com/jinzhu/now v1.1.4 // indirect
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible // indirect github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.2 // indirect
github.com/leodido/go-urn v1.2.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect
github.com/magiconair/properties v1.8.5 // indirect github.com/magiconair/properties v1.8.5 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
@@ -49,6 +62,8 @@ require (
github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.18.0 // indirect github.com/onsi/gomega v1.18.0 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/spf13/afero v1.8.0 // indirect github.com/spf13/afero v1.8.0 // indirect
github.com/spf13/cast v1.4.1 // indirect github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect
@@ -59,8 +74,8 @@ require (
github.com/ugorji/go/codec v1.2.6 // indirect github.com/ugorji/go/codec v1.2.6 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect go.uber.org/multierr v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.9 // indirect golang.org/x/tools v0.1.9 // indirect

52
go.sum
View File

@@ -44,6 +44,9 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.32.0 h1:P+RUjEaRU0GMMbYexGMDyrMkLhbbBVUVISDywi+IlFU=
github.com/Shopify/sarama v1.32.0/go.mod h1:+EmJJKZWVT/faR9RcOxJerP+LId4iWdQPBGLy1Y1Njs=
github.com/Shopify/toxiproxy/v2 v2.3.0/go.mod h1:KvQTtB6RjCJY4zqNJn7C7JDFgsG5uoHYDirfUfpIm0c=
github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs=
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/baidubce/bce-sdk-go v0.9.112 h1:qHzFxG7fwGbXCv+1smcbWFhWl6iwoXDVzPn9TUtrlss= github.com/baidubce/bce-sdk-go v0.9.112 h1:qHzFxG7fwGbXCv+1smcbWFhWl6iwoXDVzPn9TUtrlss=
@@ -63,6 +66,12 @@ 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/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -71,6 +80,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
@@ -144,6 +155,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -157,6 +170,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -180,6 +194,12 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@@ -187,6 +207,17 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA=
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
@@ -203,6 +234,9 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.2 h1:3WH+AG7s2+T8o3nrM/8u2rdqUEcQhmga7smjrT41nAw=
github.com/klauspost/compress v1.15.2/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 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/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -260,6 +294,8 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -268,6 +304,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -276,6 +314,7 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60= github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60=
@@ -313,6 +352,9 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.0/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -340,6 +382,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -347,6 +390,9 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+Wr
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI= golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc=
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -419,10 +465,13 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8= golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8=
golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -456,6 +505,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -498,12 +548,14 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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.5/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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
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=

View File

@@ -31,7 +31,7 @@ func SaveArticleHandler(c *gin.Context) {
return return
} }
colMap := models.MapJ2c[models.BackArticle](jsonMap, true) colMap := models.MapJ2c[models.BackArticle](jsonMap, true)
if ok := article.SaveArticle(colMap); !ok { if ok := article.SaveArticle(claims, colMap); !ok {
ServerErr(c, "Save Failed") ServerErr(c, "Save Failed")
return return
} }
@@ -90,7 +90,7 @@ func ListArticlesByUser(c *gin.Context) {
func DeleteArticleHandler(c *gin.Context) { func DeleteArticleHandler(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id")) id, err := strconv.Atoi(c.Param("id"))
claims := utils.ClaimsFromHeader(c) claims := utils.ClaimsFromHeader(c)
if claims.Role == global.ROLE_ID_MAP["ADMIN"] { if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c) Forbidden(c)
return return
} }
@@ -140,7 +140,7 @@ func GetArticleHandler(c *gin.Context) {
func PublishArticleHandler(c *gin.Context) { func PublishArticleHandler(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id")) id, err := strconv.Atoi(c.Param("id"))
claims := utils.ClaimsFromHeader(c) claims := utils.ClaimsFromHeader(c)
if claims.Role == global.ROLE_ID_MAP["ADMIN"] { if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c) Forbidden(c)
return return
} }

View File

@@ -1,6 +1,7 @@
package handler package handler
import ( import (
"nCovTrack-Backend/global"
"nCovTrack-Backend/service/management" "nCovTrack-Backend/service/management"
"nCovTrack-Backend/utils" "nCovTrack-Backend/utils"
"strconv" "strconv"
@@ -8,8 +9,20 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
//PullContactHandler pull contact from faker
// @Tags Management
// @Produce json
// @Summary pull contact from faker
// @Success 200 {object} utils.GinResponse
// @Router /management/faker/{patientId} [get]
// @Param Token header string true "Token"
// @Param patientId path int true "Patient Id"
func PullContactHandler(c *gin.Context) { func PullContactHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c) claims := utils.ClaimsFromHeader(c)
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c)
return
}
patientId, _ := strconv.Atoi(c.Param("patientId")) patientId, _ := strconv.Atoi(c.Param("patientId"))
rowsAffected := management.PullFromFaker(claims, patientId) rowsAffected := management.PullFromFaker(claims, patientId)
if rowsAffected == -1 { if rowsAffected == -1 {
@@ -19,13 +32,82 @@ func PullContactHandler(c *gin.Context) {
utils.Succ(c, map[string]interface{}{"pullAmount": rowsAffected}) utils.Succ(c, map[string]interface{}{"pullAmount": rowsAffected})
} }
//GetObservationHandler get observation's info
// @Tags Management
// @Produce json
// @Summary get observation's info
// @Success 200 {object} utils.GinResponse{data=models.BackObservation}
// @Router /management/observation/{id} [get]
// @Param token header string true "token"
// @Param id path int true "id"
func GetObservationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
id, _ := strconv.Atoi(c.Param("id"))
utils.Succ(c, management.GetObservation(id))
}
//ListObservationsHandler list observations by query
// @Tags Management
// @Produce json
// @Summary list observations by query
// @Success 200 {object} utils.GinResponse{data=[]models.ListObservation}
// @Router /management/observation/ [get]
// @Param Token header string true "token"
// @Param queries query models.BackObservation true "queries"
func ListObservationsHandler(c *gin.Context) { func ListObservationsHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
jsonMap := bindQuery(c) jsonMap := bindQuery(c)
utils.Succ(c, management.ListObservation(jsonMap)) utils.Succ(c, management.ListObservation(jsonMap))
} }
//TreeifyObservationHandler get transform chain by user
// @Tags Management
// @Produce json
// @Summary get transform chain by user
// @Success 200 {object} utils.GinResponse{data=models.TreeObservation}
// @Router /management/observation/tree/{id}/{direction} [get]
// @Param Token header string true "token"
// @Param id path int true "id"
// @Param direction path string true "direction" Enums(up, down, all)
func TreeifyObservationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
id, _ := strconv.Atoi(c.Param("id"))
direction := c.Param("direction")
tree := management.TreeifyObservations(id, direction)
utils.Succ(c, tree)
}
//InsertObservationHandler insert observation
// @Tags Management
// @Accept json
// @Produce json
// @Summary insert observation
// @Success 200 {object} utils.GinResponse
// @Router /management/observation/ [post]
// @Param Observation body models.BackObservation true "observation"
// @Param Token header string true "token"
func InsertObservationHandler(c *gin.Context) { func InsertObservationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c) claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
observaion := bindJson(c) observaion := bindJson(c)
delete(observaion, "id") delete(observaion, "id")
ok := management.InsertObservation(claims, observaion) ok := management.InsertObservation(claims, observaion)
@@ -36,18 +118,65 @@ func InsertObservationHandler(c *gin.Context) {
} }
} }
func GetObservationHandler(c *gin.Context) { //UpdateObservationHandler update observation
id, _ := strconv.Atoi(c.Param("id")) // @Tags Management
utils.Succ(c, management.GetObservation(id)) // @Accept json
// @Produce json
// @Summary update observation
// @Success 200 {object} utils.GinResponse
// @Router /management/observation/ [put]
// @Param Observation body models.BackObservation true "observation"
// @Param Token header string true "token"
func UpdateObservationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
observation := bindJson(c)
ok := management.UpdateObservation(claims, observation)
if ok {
utils.Succ(c, nil)
} else {
OperationFailed(c)
}
} }
//ListLocationHandler list locations
// @Tags Management
// @Produce json
// @Summary list locations
// @Success 200 {object} utils.GinResponse{data=models.BackLocation}
// @Router /management/location/ [get]
// @Param queries query models.BackLocation true "queries"
// @Param Token header string true "token"
func ListLocationHandler(c *gin.Context) { func ListLocationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"], global.ROLE_ID_MAP["VOLUNTEER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
queryMap := bindQuery(c) queryMap := bindQuery(c)
utils.Succ(c, management.ListLocation(queryMap)) utils.Succ(c, management.ListLocation(queryMap))
} }
//InsertLocationHandler insert location
// @Tags Management
// @Accept json
// @Produce json
// @Summary insert location
// @Success 200 {object} utils.GinResponse
// @Router /management/location/ [post]
// @Param Location body models.BackLocation true "location"
// @Param Token header string true "token"
func InsertLocationHandler(c *gin.Context) { func InsertLocationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c) claims := utils.ClaimsFromHeader(c)
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c)
return
}
locationMap := bindJson(c) locationMap := bindJson(c)
ok := management.InsertLocation(claims, locationMap) ok := management.InsertLocation(claims, locationMap)
if ok { if ok {
@@ -57,7 +186,20 @@ func InsertLocationHandler(c *gin.Context) {
} }
} }
//DeleteLocationHandler delete location
// @Tags Management
// @Produce json
// @Summary delete location
// @Success 200 {object} utils.GinResponse
// @Router /management/location/{id} [delete]
// @Param Token header string true "token"
// @Param Id path int true "Id"
func DeleteLocationHandler(c *gin.Context) { func DeleteLocationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
if claims.Role != global.ROLE_ID_MAP["ADMIN"] {
Forbidden(c)
return
}
id, _ := strconv.Atoi(c.Param("id")) id, _ := strconv.Atoi(c.Param("id"))
ok := management.DeleteLocation(id) ok := management.DeleteLocation(id)
if ok { if ok {
@@ -66,3 +208,27 @@ func DeleteLocationHandler(c *gin.Context) {
OperationFailed(c) OperationFailed(c)
} }
} }
//InsertPcrHandler insert pcr record
// @Tags Management
// @Produce json
// @Summary insert pcr record
// @Success 200 {object} utils.GinResponse
// @Router /management/pcr/ [post]
// @Param Pcr body models.BackPcr true "Pcr"
// @Param Token header string true "token"
func InsertPcrHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
allowRows := []int{global.ROLE_ID_MAP["ADMIN"], global.ROLE_ID_MAP["WORKER"]}
if !utils.Contains(allowRows, claims.Role) {
Forbidden(c)
return
}
jsonMap := bindJson(c)
ok := management.InsertPcr(claims, jsonMap)
if ok {
utils.Succ(c, nil)
} else {
OperationFailed(c)
}
}

65
handler/notify.go Normal file
View File

@@ -0,0 +1,65 @@
package handler
import (
"nCovTrack-Backend/models"
"nCovTrack-Backend/service/notify"
"nCovTrack-Backend/utils"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
//InsertNotificationHandler for test
func InsertNotificationHandler(c *gin.Context) {
sendNotify := models.SendInfo{Region: []string{"江苏 徐州"}, Channel: []int{1, 0}, Notification: models.BackNotification{Time: time.Now(), Kind: "测试", Content: "Test"}}
notify.SendNotify(sendNotify)
}
//CountNotificationHandler count the notification
// @Tags Notification
// @Produce json
// @Summary count the notification
// @Success 200 {object} utils.GinResponse
// @Router /notify/count/ [get]
// @Param Token header string true "token"
func CountNotificationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
count := notify.QueryNotificationLen(claims.Region)
utils.Succ(c, map[string]interface{}{"count": count})
}
//ListNotificationHandler list the notifications in the range
// @Tags Notification
// @Produce json
// @Summary list the notification in the range
// @Success 200 {object} utils.GinResponse{data=[]models.BackNotification}
// @Router /notify/{start}/{end} [get]
// @Param Token header string true "token"
// @Param start path int true "start"
// @Param end path int true "end"
func ListNotificationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
start, _ := strconv.Atoi(c.Param("start"))
end, _ := strconv.Atoi(c.Param("end"))
notifications := notify.ListNotifycation(claims.Region, start, end)
utils.Succ(c, notifications)
}
//DeleteNotificationHandler delete the notify by index
// @Tags Notification
// @Produce json
// @Summary delete the notify by index, if -1 delete all
// @Success 200 {object} utils.GinResponse
// @Router /notify/{index} [delete]
// @Param Token header string true "token"
// @Param index path int true "index"
func DeleteNotificationHandler(c *gin.Context) {
claims := utils.ClaimsFromHeader(c)
index, _ := strconv.Atoi(c.Param("index"))
if index == -1 {
notify.CleanNotification(claims.Region)
}
notify.DeleteNotification(claims.Region, index)
utils.Succ(c, nil)
}

View File

@@ -24,11 +24,13 @@ func UserRegisterHandler(c *gin.Context) {
return return
} }
registered := user.NoDuplicatePhoneOrEmail(jsonMap["phone"].(string), jsonMap["email"].(string)) registered := user.NoDuplicatePhoneOrEmail(jsonMap["phone"].(string), jsonMap["email"].(string))
if registered { if !registered {
utils.Success(c, 200, 200, "Registered", nil) utils.Success(c, 200, 200, "Registered", nil)
return
} }
colMap := models.MapJ2c[models.BackUser](jsonMap, true) colMap := models.MapJ2c[models.BackUser](jsonMap, true)
user.Register(colMap) user.Register(colMap)
utils.Succ(c, nil)
} }
//UserApproveHandler admin approve account //UserApproveHandler admin approve account

View File

@@ -10,6 +10,8 @@ func Initialize() *gin.Engine {
initRedis() initRedis()
initBos() initBos()
initCron() initCron()
go initProducer()
go initConsumer()
g := initRouter() g := initRouter()
initSwagger() initSwagger()
return g return g

70
initialize/kafka.go Normal file
View File

@@ -0,0 +1,70 @@
package initialize
import (
"nCovTrack-Backend/global"
"nCovTrack-Backend/service/notify"
"time"
"github.com/Shopify/sarama"
)
func initProducer() {
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Partitioner = sarama.NewRandomPartitioner
config.Producer.Return.Successes = true
config.Producer.Return.Errors = true
producer, err := sarama.NewSyncProducer(global.ServerSettings.Kafka.Servers, config)
if err != nil {
panic("kafka init failed")
}
// defer producer.Close()
for {
select {
case value := <-global.KafkaProducerChan:
producer.SendMessage(&sarama.ProducerMessage{Topic: global.ServerSettings.Kafka.Topic, Key: nil, Value: sarama.ByteEncoder(value)})
}
}
}
func initConsumer() {
config := sarama.NewConfig()
config.Consumer.Offsets.CommitInterval = 1 * time.Second
client, err := sarama.NewClient(global.ServerSettings.Kafka.Servers, config)
if err != nil {
panic("kafka init failed")
}
defer client.Close()
offsetManager, err := sarama.NewOffsetManagerFromClient("", client)
if err != nil {
panic("kafka init failed")
}
defer offsetManager.Close()
partitionOffsetManager, err := offsetManager.ManagePartition(global.ServerSettings.Kafka.Topic, int32(global.ServerSettings.Kafka.Partition))
if err != nil {
panic("kafka init failed")
}
defer partitionOffsetManager.Close()
offsetNewest, _ := partitionOffsetManager.NextOffset()
consumer, err := sarama.NewConsumer(global.ServerSettings.Kafka.Servers, config)
if err != nil {
panic("kafka init failed")
}
defer consumer.Close()
partitionConsumer, err := consumer.ConsumePartition(global.ServerSettings.Kafka.Topic, int32(global.ServerSettings.Kafka.Partition), offsetNewest)
if err != nil {
panic("kafka init failed")
}
defer partitionConsumer.Close()
for {
select {
case msg := <-partitionConsumer.Messages():
ConsumeFunc(msg.Value)
}
}
}
func ConsumeFunc(msg []byte) {
notify.HandleKafkaNotify(msg)
}

View File

@@ -3,11 +3,20 @@ package main
import ( import (
"nCovTrack-Backend/global" "nCovTrack-Backend/global"
"nCovTrack-Backend/initialize" "nCovTrack-Backend/initialize"
"os"
"os/signal"
"syscall"
) )
// @title nCov Tracker // @title nCov Tracker
// @version 1.0 // @version 1.0
func main() { func main() {
signals := make(chan os.Signal)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
go func() {
<-signals
os.Exit(1)
}()
gin := initialize.Initialize() gin := initialize.Initialize()
gin.Run(global.GetListenOn()) gin.Run(global.GetListenOn())
} }

View File

@@ -6,7 +6,7 @@ import (
// BackArticle article struct // BackArticle article struct
type BackArticle struct { type BackArticle struct {
ID int `gorm:"primaryKey;column:id" json:"-"` // 文章id ID int `gorm:"primaryKey;column:id" json:"id"` // 文章id
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 文章新建时间 CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 文章新建时间
CreateUser int `gorm:"column:create_user" json:"createUser"` // 文章创建者id CreateUser int `gorm:"column:create_user" json:"createUser"` // 文章创建者id
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 文章最后更新时间 ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 文章最后更新时间
@@ -21,7 +21,7 @@ type BackArticle struct {
} }
type ListArticle struct { type ListArticle struct {
ID int `json:"-"` ID int `json:"id"`
Username string `json:"username"` Username string `json:"username"`
CreateTime time.Time `json:"createTime"` CreateTime time.Time `json:"createTime"`
ModifyTime time.Time `json:"modifyTime"` ModifyTime time.Time `json:"modifyTime"`
@@ -34,13 +34,3 @@ type ListArticle struct {
func init() { func init() {
initJcMap[BackArticle]() initJcMap[BackArticle]()
} }
//func ArticleMapJ2c(jsonMap map[string]interface{}, ignoreNil bool) map[string]interface{} {
// colMap := make(map[string]interface{})
// for k, v := range jsonMap {
// if colKey := colKey != "" && (!ignoreNil && v == nil) {
// colMap[colKey] = v
// }
// }
// return colMap
//}

1
models/kafka.go Normal file
View File

@@ -0,0 +1 @@
package models

View File

@@ -63,7 +63,7 @@ type BackSituationRecord struct {
IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志 IsDelete int `gorm:"column:is_delete" json:"isDelete"` // 删除标志
} }
type ListObeservation struct { type ListObservation struct {
ID int `json:"id"` ID int `json:"id"`
Name string `json:"name"` // 姓名 Name string `json:"name"` // 姓名
Age int `json:"age"` // 年龄 Age int `json:"age"` // 年龄
@@ -82,11 +82,32 @@ type ListObeservation struct {
ModifyUser int `json:"modifyUser"` // 修改者 ModifyUser int `json:"modifyUser"` // 修改者
ModifyTime time.Time `json:"modifyTime"` // 修改时间 ModifyTime time.Time `json:"modifyTime"` // 修改时间
PcrTime time.Time `json:"pcrTime"` // 核酸时间 PcrTime time.Time `json:"pcrTime"` // 核酸时间
PcrResult int `json:"pcrResult"` //核酸结果 PcrResult int `json:"pcrResult"` // 核酸结果0-未检测1-阴性2-阳性
RecordTime time.Time `json:"recordTime"` // 状态转换时间 RecordTime time.Time `json:"recordTime"` // 状态转换时间
Record string `json:"record"` // 状态转换内容 Record string `json:"record"` // 状态转换内容
} }
type TreeObservation struct {
ID int `json:"id"`
Name string `json:"name"` // 姓名
Age int `json:"age"` // 年龄
Sex int `json:"sex"` // 性别
Phone string `json:"phone"` // 手机号码
Identification string `json:"identification"` // 身份证号
ContactPerson int `json:"contactPerson"` // 接触者id
Region string `json:"region"` // 受观察者所在区域
Address string `json:"address"` // 受观察者所在具体地点
HealthSituation int `json:"healthSituation"` // 被观察者的疫情状况0- 其他1-患者2-密接3-次密接
HealthChangeTime time.Time `json:"healthChangeTime"` // 患者健康状况转化时间
MeasureSituation int `json:"measureSituation"` // 受观察者被采取措施状况 0-未采取措施1-解除风险2-正在治疗3-集中隔离4-居家隔离
Trajectory string `json:"trajectory"` // 行程轨迹
CreateUser int `json:"createUser"` // 创建者
CreateTime time.Time `json:"createTime"` // 创建时间
ModifyUser int `json:"modifyUser"` // 修改者
ModifyTime time.Time `json:"modifyTime"` // 修改时间
Children []*TreeObservation `json:"children"` // 子结点
}
type QueryObservation struct { type QueryObservation struct {
BackObservation BackObservation
PcrRecord []BackPcr `json:"pcrRecord"` PcrRecord []BackPcr `json:"pcrRecord"`

View File

@@ -4,6 +4,12 @@ import "time"
type BackNotification struct { type BackNotification struct {
Time time.Time `json:"time"` Time time.Time `json:"time"`
Kind int `json:"kind"` Kind string `json:"kind"`
Content string `json:"content"` Content string `json:"content"`
} }
type SendInfo struct {
Region []string `json:"region"`
Channel []int `json:"channel"`
Notification BackNotification `json:"notification"`
}

View File

@@ -2,11 +2,13 @@ package models
import ( import (
"fmt" "fmt"
"gorm.io/gorm"
"nCovTrack-Backend/global" "nCovTrack-Backend/global"
"reflect" "reflect"
"regexp" "regexp"
"strconv"
"time" "time"
"gorm.io/gorm"
) )
var colNameReg, _ = regexp.Compile(".*column:(.*);?") var colNameReg, _ = regexp.Compile(".*column:(.*);?")
@@ -124,7 +126,7 @@ func BeforeBatchSave(colMaps *[]map[string]interface{}, user int) {
func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64) { func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64) {
var tx *gorm.DB var tx *gorm.DB
if colMap["id"] == nil || int(colMap["id"].(float64)) == 0 { if colMap["id"] == nil || getMapId(colMap["id"]) == 0 {
tx = global.Db.Model(new(T)).Create(colMap) tx = global.Db.Model(new(T)).Create(colMap)
} else { } else {
tx = global.Db.Model(new(T)).Where("id = ?", colMap["id"]).Updates(colMap) tx = global.Db.Model(new(T)).Where("id = ?", colMap["id"]).Updates(colMap)
@@ -169,7 +171,7 @@ func DeleteById[T any](id int) (ok bool, rowsAffected int64) {
if tx.Error != nil { if tx.Error != nil {
return false, 0 return false, 0
} }
return true, rowsAffected return true, tx.RowsAffected
} }
func DropById[T any](id int) { func DropById[T any](id int) {
@@ -253,3 +255,17 @@ func CountByOrm(tx *gorm.DB) int64 {
tx.Count(&count) tx.Count(&count)
return count return count
} }
func getMapId(id interface{}) int {
switch id.(type) {
case int:
return id.(int)
case string:
id, _ := strconv.Atoi(id.(string))
return id
case float64:
return int(id.(float64))
default:
return -1
}
}

View File

@@ -6,12 +6,18 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func managementPublicRouter(router *gin.RouterGroup) { func managementPrivateRouter(router *gin.RouterGroup) {
managementRouter := router.Group("/management") managementRouter := router.Group("/management")
{ {
managementRouter.GET("/observation/contact/pull/:patientId", handler.PullContactHandler) managementRouter.GET("/faker/:patientId", handler.PullContactHandler)
managementRouter.GET("/observation", handler.ListObservationsHandler) managementRouter.GET("/observation", handler.ListObservationsHandler)
managementRouter.POST("/observation", handler.InsertObservationHandler) managementRouter.POST("/observation", handler.InsertObservationHandler)
managementRouter.GET("/observation/:id", handler.GetObservationHandler) managementRouter.GET("/observation/:id", handler.GetObservationHandler)
managementRouter.GET("/observation/tree/:id/:direction", handler.TreeifyObservationHandler)
managementRouter.PUT("/observation", handler.UpdateObservationHandler)
managementRouter.POST("/location/", handler.InsertLocationHandler)
managementRouter.GET("/location/", handler.ListLocationHandler)
managementRouter.DELETE("/location/", handler.DeleteLocationHandler)
managementRouter.POST("/pcr/", handler.InsertPcrHandler)
} }
} }

17
router/notify.go Normal file
View File

@@ -0,0 +1,17 @@
package router
import (
"nCovTrack-Backend/handler"
"github.com/gin-gonic/gin"
)
func notifyPrivateRouter(router *gin.RouterGroup) {
notifyRouter := router.Group("/notify")
{
notifyRouter.GET("/count", handler.CountNotificationHandler)
notifyRouter.POST("/", handler.InsertNotificationHandler)
notifyRouter.GET("/:start/:end", handler.ListNotificationHandler)
notifyRouter.DELETE("/:index", handler.DeleteNotificationHandler)
}
}

View File

@@ -15,12 +15,13 @@ func BusiRouter() {
statisticRouter(publicRouter) statisticRouter(publicRouter)
articlePublicRouter(publicRouter) articlePublicRouter(publicRouter)
userPublicRouter(publicRouter) userPublicRouter(publicRouter)
managementPublicRouter(publicRouter)
} }
// Private // Private
{ {
articlePrivateRouter(privateRouter) articlePrivateRouter(privateRouter)
userPrivateRouter(privateRouter) userPrivateRouter(privateRouter)
notifyPrivateRouter(privateRouter)
managementPrivateRouter(privateRouter)
} }
} }

View File

@@ -39,8 +39,8 @@ func listArticles(isPublish int, createUser int) *[]models.ListArticle {
} }
//SaveArticle save the articles //SaveArticle save the articles
func SaveArticle(article map[string]interface{}) (ok bool) { func SaveArticle(claims models.TokenClaims, article map[string]interface{}) (ok bool) {
models.BeforeSave(article, -1) models.BeforeSave(article, claims.ID)
ok, rows := models.Upsert[models.BackArticle](article) ok, rows := models.Upsert[models.BackArticle](article)
return ok && rows != 0 return ok && rows != 0
} }

View File

@@ -10,6 +10,7 @@ import (
"time" "time"
) )
//fakerGetRequest Get data from faker
func fakerGetRequest(uri string) string { func fakerGetRequest(uri string) string {
resStr := utils.GetWhioutHeader(global.FACKER_HOST + uri) resStr := utils.GetWhioutHeader(global.FACKER_HOST + uri)
var res utils.GinResponse var res utils.GinResponse
@@ -18,6 +19,7 @@ func fakerGetRequest(uri string) string {
return string(dataStr) return string(dataStr)
} }
//queryHotelContacts Hotel contacts
func queryHotelContacts(identification string) []models.HotelContactRequest { func queryHotelContacts(identification string) []models.HotelContactRequest {
dataStr := fakerGetRequest("query/contacts/hotel/" + identification) dataStr := fakerGetRequest("query/contacts/hotel/" + identification)
var data []models.HotelContactRequest var data []models.HotelContactRequest
@@ -28,6 +30,7 @@ func queryHotelContacts(identification string) []models.HotelContactRequest {
return data return data
} }
//queryRailwayContacts Railway contacts
func queryRailwayContacts(identification string) []models.RailwayContactRequest { func queryRailwayContacts(identification string) []models.RailwayContactRequest {
dataStr := fakerGetRequest("query/contacts/railway/" + identification) dataStr := fakerGetRequest("query/contacts/railway/" + identification)
var data []models.RailwayContactRequest var data []models.RailwayContactRequest
@@ -38,7 +41,8 @@ func queryRailwayContacts(identification string) []models.RailwayContactRequest
return data return data
} }
func queryPatients(identification string) []models.PatientRequest { //queryPatients Patients
func QueryPatients(identification string) []models.PatientRequest {
dataStr := fakerGetRequest("query/contacts/railway/" + identification) dataStr := fakerGetRequest("query/contacts/railway/" + identification)
var data []models.PatientRequest var data []models.PatientRequest
err := json.Unmarshal([]byte(dataStr), &data) err := json.Unmarshal([]byte(dataStr), &data)
@@ -48,6 +52,7 @@ func queryPatients(identification string) []models.PatientRequest {
return data return data
} }
//queryContacts Resolve the diffrent of hotel and railway request
func queryContacts(identification string) []models.BackObservation { func queryContacts(identification string) []models.BackObservation {
hotelContacts := queryHotelContacts(identification) hotelContacts := queryHotelContacts(identification)
railwayContacts := queryRailwayContacts(identification) railwayContacts := queryRailwayContacts(identification)
@@ -55,11 +60,13 @@ func queryContacts(identification string) []models.BackObservation {
return observations return observations
} }
//splitFakerAddress Extract the region
func splitFakerAddress(fakerAddress string) string { func splitFakerAddress(fakerAddress string) string {
addresses := strings.Split(fakerAddress, " ") addresses := strings.Split(fakerAddress, " ")
return addresses[1] + " " + addresses[2] return addresses[1] + " " + addresses[2]
} }
//fakerContacts2Observations Convvert structs
func fakerContacts2Observations(contacts any) []models.BackObservation { func fakerContacts2Observations(contacts any) []models.BackObservation {
var observations []models.BackObservation var observations []models.BackObservation
switch contacts.(type) { switch contacts.(type) {

View File

@@ -4,6 +4,7 @@ import (
"nCovTrack-Backend/models" "nCovTrack-Backend/models"
) )
//InsertLocation Insert locations
func InsertLocation(claims models.TokenClaims, locationJMap map[string]interface{}) bool { func InsertLocation(claims models.TokenClaims, locationJMap map[string]interface{}) bool {
locationCMap := models.MapJ2c[models.BackLocation](locationJMap, true) locationCMap := models.MapJ2c[models.BackLocation](locationJMap, true)
models.BeforeSave(locationCMap, claims.ID) models.BeforeSave(locationCMap, claims.ID)
@@ -11,11 +12,13 @@ func InsertLocation(claims models.TokenClaims, locationJMap map[string]interface
return (ok && rowsAffected != 0) return (ok && rowsAffected != 0)
} }
//ListLocation List locations
func ListLocation(queryJMap map[string]any) *[]map[string]any { func ListLocation(queryJMap map[string]any) *[]map[string]any {
queryCMap := models.MapJ2c[models.BackLocation](queryJMap, true) queryCMap := models.MapJ2c[models.BackLocation](queryJMap, true)
return models.ListField[models.BackLocation]([]map[string]any{queryCMap}, true, "is_delete") return models.ListField[models.BackLocation]([]map[string]any{queryCMap}, true, "is_delete")
} }
//DeleteLocation Delete locations
func DeleteLocation(id int) bool { func DeleteLocation(id int) bool {
ok, rowsAffected := models.DeleteById[models.BackLocation](id) ok, rowsAffected := models.DeleteById[models.BackLocation](id)
return (ok && rowsAffected != 0) return (ok && rowsAffected != 0)

View File

@@ -4,10 +4,12 @@ import (
"fmt" "fmt"
"nCovTrack-Backend/global" "nCovTrack-Backend/global"
"nCovTrack-Backend/models" "nCovTrack-Backend/models"
"nCovTrack-Backend/service/notify"
"nCovTrack-Backend/utils" "nCovTrack-Backend/utils"
"time" "time"
) )
//PullFromFaker Pull observations from faker system
func PullFromFaker(claims models.TokenClaims, patientId int) int64 { func PullFromFaker(claims models.TokenClaims, patientId int) int64 {
// Get patient's identification by id // Get patient's identification by id
queryMap := []map[string]interface{}{{"id": patientId}} queryMap := []map[string]interface{}{{"id": patientId}}
@@ -28,31 +30,39 @@ func PullFromFaker(claims models.TokenClaims, patientId int) int64 {
observationsCMap := models.MapsJ2c[models.BackObservation](observationsJMap, false) observationsCMap := models.MapsJ2c[models.BackObservation](observationsJMap, false)
models.BeforeBatchSave(&observationsCMap, claims.ID) models.BeforeBatchSave(&observationsCMap, claims.ID)
_, rowsAffected := models.BatchInsert[models.BackObservation](observationsCMap) _, rowsAffected := models.BatchInsert[models.BackObservation](observationsCMap)
// Generate situation record // Generate situation record and send notify to the region
if rowsAffected != 0 { if rowsAffected != 0 {
pullSituationRecord(claims, observations) pullSituationRecord(claims, observations)
pullNotify(observations)
} }
return rowsAffected return rowsAffected
} }
func ListObservation(jsonMap map[string]interface{}) []models.ListObeservation { //ListObservation list observations with query
func ListObservation(jsonMap map[string]interface{}) []models.ListObservation {
colMap := models.MapJ2c[models.BackObservation](jsonMap, true) colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
queryMap := []map[string]interface{}{colMap} queryMap := []map[string]interface{}{colMap}
return listObservation(queryMap) return listObservation(queryMap)
} }
//GetObservation get observation by id
func GetObservation(id int) map[string]interface{} { func GetObservation(id int) map[string]interface{} {
// Obseration
observationCMap := models.GetField[models.BackObservation]([]map[string]interface{}{{"id": id}}, true, "is_delete") observationCMap := models.GetField[models.BackObservation]([]map[string]interface{}{{"id": id}}, true, "is_delete")
observationJMap := models.MapC2j[models.BackObservation](observationCMap, true) observationJMap := models.MapC2j[models.BackObservation](observationCMap, true)
// Pcr record
pcrRecordCMap := models.ListField[models.BackPcr]([]map[string]interface{}{{"observation": id}}, true, "is_delete") pcrRecordCMap := models.ListField[models.BackPcr]([]map[string]interface{}{{"observation": id}}, true, "is_delete")
pcrRecordJMap := models.MapsC2j[models.BackPcr](*pcrRecordCMap, true) pcrRecordJMap := models.MapsC2j[models.BackPcr](*pcrRecordCMap, true)
// Situation record
situationRecordCMap := models.ListField[models.BackSituationRecord]([]map[string]interface{}{{"observation": id}}, true, "is_delete") situationRecordCMap := models.ListField[models.BackSituationRecord]([]map[string]interface{}{{"observation": id}}, true, "is_delete")
situationRecordJMap := models.MapsC2j[models.BackSituationRecord](*situationRecordCMap, true) situationRecordJMap := models.MapsC2j[models.BackSituationRecord](*situationRecordCMap, true)
// Assemble
observationJMap["pcrRecord"] = pcrRecordJMap observationJMap["pcrRecord"] = pcrRecordJMap
observationJMap["situationRecord"] = situationRecordJMap observationJMap["situationRecord"] = situationRecordJMap
return observationJMap return observationJMap
} }
//InsertObservation add observation
func InsertObservation(claims models.TokenClaims, jsonMap map[string]interface{}) bool { func InsertObservation(claims models.TokenClaims, jsonMap map[string]interface{}) bool {
colMap := models.MapJ2c[models.BackObservation](jsonMap, true) colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
models.BeforeSave(colMap, claims.ID) models.BeforeSave(colMap, claims.ID)
@@ -65,17 +75,103 @@ func InsertObservation(claims models.TokenClaims, jsonMap map[string]interface{}
} }
func UpdateObservation(claims models.TokenClaims, jsonMap map[string]any) bool { func UpdateObservation(claims models.TokenClaims, jsonMap map[string]any) bool {
// Pre actions
colMap := models.MapJ2c[models.BackObservation](jsonMap, true) colMap := models.MapJ2c[models.BackObservation](jsonMap, true)
models.BeforeSave(colMap, claims.ID) models.BeforeSave(colMap, claims.ID)
oldMap := models.Get[models.BackObservation]([]map[string]interface{}{{"id": jsonMap["id"]}}) queryMap := []map[string]interface{}{{"id": jsonMap["id"]}}
insertSituationRecord(claims, oldMap, colMap) // Get old record
oldMap := models.Get[models.BackObservation](queryMap)
if oldMap == nil || len(oldMap) == 0 {
return false return false
} }
// Deal with region update
if colMap["region"] != nil && oldMap["region"].(string) != colMap["region"].(string) {
updateObservationRegion(colMap["region"].(string))
}
// Deal with situation update
if colMap["health_situation"] != nil && int(colMap["health_situation"].(float64)) != oldMap["health_situation"].(int) ||
colMap["measure_situation"] != nil && int(colMap["measure_situation"].(float64)) != oldMap["measure_situation"].(int) {
updateSituation(claims, oldMap, colMap)
}
ok, rowsAffected := models.Update[models.BackObservation](queryMap, colMap)
return ok && rowsAffected != 0
}
//TreeifyObservations get the transmission chains of observations
// Param direction: up, down, all
func TreeifyObservations(observationId int, direction string) *models.TreeObservation {
// Get arrays form back observation
var observations []models.BackObservation
if direction != "down" {
observations = append(observations, treeifyObservations(observationId, true)...)
}
if direction != "up" {
observations = append(observations, treeifyObservations(observationId, false)...)
}
// Treeify
observationMap := map[int]*models.TreeObservation{}
for _, observation := range observations {
observationMap[observation.ID] = &models.TreeObservation{
ID: observation.ID,
Name: observation.Name,
Age: observation.Age,
Sex: observation.Sex,
Phone: observation.Phone,
Identification: observation.Identification,
ContactPerson: observation.ContactPerson,
Region: observation.Region,
Address: observation.Address,
HealthSituation: observation.HealthSituation,
HealthChangeTime: observation.HealthChangeTime,
CreateUser: observation.CreateUser,
CreateTime: observation.CreateTime,
ModifyUser: observation.ModifyUser,
ModifyTime: observation.ModifyTime,
}
}
var rootKey int
for k := range observationMap {
parentId := observationMap[k].ContactPerson
parent := observationMap[parentId]
if parent == nil {
rootKey = k
continue
}
parent.Children = append(parent.Children, observationMap[k])
}
return observationMap[rootKey]
}
//treeifyObservations query tree data from db
// Param direction up: true, down: false
func treeifyObservations(observationId int, direction bool) []models.BackObservation {
var res []models.BackObservation
var directionCond string
if direction {
directionCond = "p.id = cte.contact_person"
} else {
directionCond = "cte.id = p.contact_person"
}
querySql := fmt.Sprintf(`
WITH RECURSIVE cte (id, name, age, sex, phone, identification, contact_person, region, address, health_situation, health_change_time, trajectory, create_user, modify_user, create_time, modify_time) AS (
SELECT id, name, age, sex, phone, identification, contact_person, region, address, health_situation, health_change_time, trajectory, create_user, modify_user, create_time, modify_time
FROM back_observation
WHERE contact_person = ?
UNION ALL
SELECT p.id, p.name, p.age, p.sex, p.phone, p.identification, p.contact_person, p.region, p.address, p.health_situation, p.health_change_time, p.trajectory, p.create_user, p.modify_user, p.create_time, p.modify_time
FROM back_observation p
INNER JOIN cte ON %s
)
SELECT * FROM cte
`, directionCond)
global.Db.Model(models.BackObservation{}).Raw(querySql, observationId).Scan(&res)
return res
}
//listObservation the queryMap need with table name //listObservation the queryMap need with table name
// @Param queryMap the colMap of models.BackObservation // Param queryMap the colMap of models.BackObservation
func listObservation(queryMap []map[string]interface{}) []models.ListObeservation { func listObservation(queryMap []map[string]interface{}) []models.ListObservation {
var observations []models.ListObeservation var observations []models.ListObservation
tx := global.Db.Model(new((models.BackObservation))). tx := global.Db.Model(new((models.BackObservation))).
Select("back_observation.*, back_pcr.detect_time AS pcr_time, detect_result AS pcr_result," + Select("back_observation.*, back_pcr.detect_time AS pcr_time, detect_result AS pcr_result," +
"back_situation_record.create_time AS record_time, back_situation_record.record AS record"). "back_situation_record.create_time AS record_time, back_situation_record.record AS record").
@@ -94,6 +190,7 @@ func listObservation(queryMap []map[string]interface{}) []models.ListObeservatio
return observations return observations
} }
//pullSituationRecord push situation record after pull observations
func pullSituationRecord(claims models.TokenClaims, observations []models.BackObservation) { func pullSituationRecord(claims models.TokenClaims, observations []models.BackObservation) {
// Query observations' id // Query observations' id
var identifications []string var identifications []string
@@ -104,7 +201,7 @@ func pullSituationRecord(claims models.TokenClaims, observations []models.BackOb
observationMaps := models.ListField[models.BackObservation](queryMap, false, "id", "identification") observationMaps := models.ListField[models.BackObservation](queryMap, false, "id", "identification")
// Assemble records // Assemble records
var records []models.BackSituationRecord var records []models.BackSituationRecord
recordContent := record00_20() recordContent := record___20()
for _, observationMap := range *observationMaps { for _, observationMap := range *observationMaps {
record := models.BackSituationRecord{Observation: observationMap["id"].(int), Record: recordContent} record := models.BackSituationRecord{Observation: observationMap["id"].(int), Record: recordContent}
records = append(records, record) records = append(records, record)
@@ -115,20 +212,87 @@ func pullSituationRecord(claims models.TokenClaims, observations []models.BackOb
recordsCMaps := models.MapsJ2c[models.BackSituationRecord](recordsJMaps, true) recordsCMaps := models.MapsJ2c[models.BackSituationRecord](recordsJMaps, true)
models.BeforeBatchSave(&recordsCMaps, claims.ID) models.BeforeBatchSave(&recordsCMaps, claims.ID)
models.BatchInsert[models.BackSituationRecord](recordsCMaps) models.BatchInsert[models.BackSituationRecord](recordsCMaps)
// Notify the admin of pull region
// Send email to the region admin
} }
//pullNotify send notify after pull observations
func pullNotify(observations []models.BackObservation) {
var regions []string
for _, observation := range observations {
regions = append(regions, observation.Region)
}
regions = utils.Distinct(regions)
notification := models.BackNotification{Time: time.Now(), Kind: "疫情", Content: "出现了新的接触者,请及时登录系统进行处理"}
sendInfo := models.SendInfo{Region: regions, Channel: []int{0, 1}, Notification: notification}
notify.SendNotify(sendInfo)
}
//updateObservationRegion send notify while update observation's region
func updateObservationRegion(region string) { func updateObservationRegion(region string) {
// Add to notify notification := models.BackNotification{Time: time.Now(), Kind: "疫情", Content: "本地有新的接触者,请及时登录系统进行处理"}
// Send email to the target region amdin sendInfo := models.SendInfo{Region: []string{region}, Channel: []int{0, 1}, Notification: notification}
notify.SendNotify(sendInfo)
} }
func updateWhileDiagnosis(claims models.TokenClaims, patientId int) { //updateSituation make some special resolve while situation update
// Update sub contact to contact and nomeasure func updateSituation(claims models.TokenClaims, oldObservationMap, newObservationMap map[string]interface{}) {
// Add to notify if newObservationMap["health_situation"] != nil {
newHealthSituation := int(newObservationMap["health_situation"].(float64))
oldHealthSituation := oldObservationMap["health_situation"].(int)
// Update health situation change time and measure_situation
if newHealthSituation != oldHealthSituation {
newObservationMap["health_change_time"] = time.Now()
newObservationMap["measure_situation"] = 0
}
// Deal with contact to patient
if oldHealthSituation == 2 && newHealthSituation == 1 {
// Query sub contacts
queryMap := []map[string]interface{}{{"contact_person": oldObservationMap["id"].(int)}}
subContacts := models.ListField[models.BackObservation](queryMap, false, "id", "region")
// Get reginos and assemble situation record
var regions []string
var subContactRecords []models.BackSituationRecord
for _, subContact := range *subContacts {
regions = append(regions, subContact["region"].(string))
subContactRecord := models.BackSituationRecord{
Observation: int(newObservationMap["id"].(float64)),
Record: record___20(),
}
subContactRecords = append(subContactRecords, subContactRecord)
}
// Update sub contact
updateMap := map[string]interface{}{
"health_situation": 2,
"health_change_time": newObservationMap["health_change_time"],
"measure_situation": 0,
}
models.Update[models.BackObservation](queryMap, updateMap)
// Insert subContacts' record
var recordJMaps []map[string]interface{}
utils.Strcut2Map(subContactRecords, &recordJMaps)
recordCMap := models.MapsJ2c[models.BackSituationRecord](recordJMaps, true)
models.BeforeBatchSave(&recordCMap, claims.ID)
models.BatchInsert[models.BackSituationRecord](recordCMap)
// Send nofity
regions = utils.Distinct(regions)
notification := models.BackNotification{
Time: newObservationMap["health_change_time"].(time.Time),
Kind: "疫情",
Content: "由于密接者转为患者,次密接者状态需要修改",
}
sendInfo := models.SendInfo{
Region: regions,
Channel: []int{0, 1},
Notification: notification,
}
notify.SendNotify(sendInfo)
}
insertSituationRecord(claims, oldObservationMap, newObservationMap)
}
} }
//insertSituationRecord insert situation record
func insertSituationRecord(claims models.TokenClaims, oldObservation, newObservation map[string]interface{}) bool { func insertSituationRecord(claims models.TokenClaims, oldObservation, newObservation map[string]interface{}) bool {
var oldSituation, newSituation string var oldSituation, newSituation string
if oldObservation["id"] == nil { if oldObservation["id"] == nil {
@@ -154,20 +318,22 @@ func insertSituationRecord(claims models.TokenClaims, oldObservation, newObserva
switch situationConvert { switch situationConvert {
case "00_10": case "00_10":
recordContent = record00_10() recordContent = record00_10()
case "00_20":
recordContent = record00_20()
case "00_30": case "00_30":
recordContent = record00_30() recordContent = record00_30()
case "00_12": case "00_12":
recordContent = record00_12(newObservation["region"].(string), newObservation["address"].(string)) recordContent = record00_12(newObservation["region"].(string), newObservation["address"].(string))
case "10_12": case "10_12":
recordContent = record10_12(newObservation["region"].(string), newObservation["address"].(string)) recordContent = record10_12(newObservation["region"].(string), newObservation["address"].(string))
case "00_20", "33_20", "34_20":
recordContent = record___20()
case "12_01", "23_01", "24_01", "33_01", "34_01": case "12_01", "23_01", "24_01", "33_01", "34_01":
recordContent = record___01() recordContent = record___01()
case "20_23", "30_33", "24_23", "34_33": case "20_23", "30_33", "24_23", "34_33":
recordContent = record____3(newObservation["region"].(string), newObservation["address"].(string)) recordContent = record____3(newObservation["region"].(string), newObservation["address"].(string))
case "20_24", "30_34", "23_24", "33_34": case "20_24", "30_34", "23_24", "33_34":
recordContent = record____4(newObservation["region"].(string), newObservation["address"].(string)) recordContent = record____4(newObservation["region"].(string), newObservation["address"].(string))
case "23_10", "24_10", "33_10", "34_10":
recordContent = record___10()
default: default:
if oldSituation != "00" { if oldSituation != "00" {
models.Upsert[models.BackObservation](oldObservation) models.Upsert[models.BackObservation](oldObservation)
@@ -193,7 +359,7 @@ func record00_12(region, address string) string {
date := utils.FormatDate(time.Now()) date := utils.FormatDate(time.Now())
return fmt.Sprintf("%s 于 %s %s 确诊为患者", date, region, address) return fmt.Sprintf("%s 于 %s %s 确诊为患者", date, region, address)
} }
func record00_20() string { func record___20() string {
date := utils.FormatDate(time.Now()) date := utils.FormatDate(time.Now())
return date + " 转为密接" return date + " 转为密接"
} }

10
service/management/pcr.go Normal file
View File

@@ -0,0 +1,10 @@
package management
import "nCovTrack-Backend/models"
func InsertPcr(claims models.TokenClaims, jsonMap map[string]interface{}) bool {
colMap := models.MapJ2c[models.BackPcr](jsonMap, true)
models.BeforeSave(colMap, claims.ID)
ok, rowsAffected := models.Upsert[models.BackPcr](colMap)
return ok && rowsAffected != 0
}

View File

@@ -4,35 +4,65 @@ import (
"encoding/json" "encoding/json"
"nCovTrack-Backend/global" "nCovTrack-Backend/global"
"nCovTrack-Backend/models" "nCovTrack-Backend/models"
"strconv" "nCovTrack-Backend/utils"
) )
type NotifyFunc func([]string, models.BackNotification)
const ( const (
NOTIFY_KEY = "notification_" NOTIFY_KEY = "notification_"
NOTIFY_DEL_VALUE = "notify_del" NOTIFY_DEL_VALUE = "notify_del"
) )
func InsertNotification(userId int, notification models.BackNotification) { var (
key := NOTIFY_KEY + strconv.Itoa(userId) NOTIFY_CHANNEL_FUNC_ARR = []NotifyFunc{notifyNotification, emailNotification}
valueStr, _ := json.Marshal(notification) )
global.Redis.RPush(key, valueStr)
//emailNotification send email
func emailNotification(regions []string, notification models.BackNotification) {
queryMap := []map[string]interface{}{{"region": regions, "role": global.ROLE_ID_MAP["ADMIN"]}}
observations := models.ListField[models.BackUser](queryMap, false, "email")
var emails []string
for _, observation := range *observations {
emails = append(emails, observation["email"].(string))
}
utils.SendEmail(notification.Kind+"通知邮件", notification.Content, emails...)
} }
func DeleteNotification(userId int, index int) { //notifyNotification add to notify system
key := NOTIFY_KEY + strconv.Itoa(userId) func notifyNotification(regions []string, notification models.BackNotification) {
valueByte, _ := json.Marshal(notification)
pipe := global.Redis.TxPipeline()
for _, region := range regions {
pipe.RPush(NOTIFY_KEY+region, valueByte)
}
pipe.Exec()
}
//DeleteNotification delete notify by id
func DeleteNotification(region string, index int) {
key := NOTIFY_KEY + region
pipe := global.Redis.TxPipeline() pipe := global.Redis.TxPipeline()
pipe.LSet(key, int64(index), NOTIFY_DEL_VALUE) pipe.LSet(key, int64(index), NOTIFY_DEL_VALUE)
pipe.LRem(key, 2, NOTIFY_DEL_VALUE) pipe.LRem(key, 2, NOTIFY_DEL_VALUE)
pipe.Exec() pipe.Exec()
} }
func QueryNotificationLen(userId int) int { //CleanNotification delete all notify
key := NOTIFY_KEY + strconv.Itoa(userId) func CleanNotification(region string) {
key := NOTIFY_KEY + region
global.Redis.Del(key)
}
//QueryNotificationLen query the count notification
func QueryNotificationLen(region string) int {
key := NOTIFY_KEY + region
return int(global.Redis.LLen(key).Val()) return int(global.Redis.LLen(key).Val())
} }
func ListNotifycation(userId int, start, end int) []models.BackNotification { //ListNotifycation list the notifications ny range
key := NOTIFY_KEY + strconv.Itoa(userId) func ListNotifycation(region string, start, end int) []models.BackNotification {
key := NOTIFY_KEY + region
var notifications []models.BackNotification var notifications []models.BackNotification
notificationStrArr := global.Redis.LRange(key, int64(start), int64(end)).Val() notificationStrArr := global.Redis.LRange(key, int64(start), int64(end)).Val()
for _, notificationStr := range notificationStrArr { for _, notificationStr := range notificationStrArr {
@@ -42,3 +72,18 @@ func ListNotifycation(userId int, start, end int) []models.BackNotification {
} }
return notifications return notifications
} }
//SendNotify send notify to kafka
func SendNotify(send models.SendInfo) {
sendInfo, _ := json.Marshal(send)
global.KafkaProducerChan <- sendInfo
}
//HandleKafkaNotify handle kafka info
func HandleKafkaNotify(sendInfoByte []byte) {
var sendInfo models.SendInfo
json.Unmarshal(sendInfoByte, &sendInfo)
for _, channel := range sendInfo.Channel {
NOTIFY_CHANNEL_FUNC_ARR[channel](sendInfo.Region, sendInfo.Notification)
}
}

View File

@@ -2,13 +2,15 @@ package user
import ( import (
"fmt" "fmt"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
"nCovTrack-Backend/global" "nCovTrack-Backend/global"
"nCovTrack-Backend/models" "nCovTrack-Backend/models"
"nCovTrack-Backend/service/notify"
"nCovTrack-Backend/utils" "nCovTrack-Backend/utils"
"strings" "strings"
"time" "time"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
) )
const ( const (
@@ -50,6 +52,15 @@ func Register(user map[string]interface{}) bool {
user["approver"] = 0 user["approver"] = 0
colMap := models.MapJ2c[models.BackUser](user, false) colMap := models.MapJ2c[models.BackUser](user, false)
ok, rowsAffected := models.Upsert[models.BackUser](colMap) ok, rowsAffected := models.Upsert[models.BackUser](colMap)
var sendRegion string
if int(user["role"].(float64)) == global.ROLE_ID_MAP["ADMIN"] {
sendRegion = strings.Split(user["region"].(string), " ")[0]
} else {
sendRegion = user["region"].(string)
}
notification := models.BackNotification{Time: time.Now(), Kind: "审批", Content: "有新的注册待审批"}
sendInfo := models.SendInfo{Region: []string{sendRegion}, Channel: []int{0}, Notification: notification}
notify.SendNotify(sendInfo)
if !ok || rowsAffected == 0 { if !ok || rowsAffected == 0 {
return false return false
} }
@@ -95,7 +106,7 @@ func ApproveRegister(claims models.TokenClaims, email string, pass bool) bool {
} else { } else {
approver = -claims.ID approver = -claims.ID
} }
updateMap := map[string]interface{}{"approver": approver} updateMap := map[string]interface{}{"approver": approver, "modify_time": time.Now()}
ok, rowsAffected := models.Update[models.BackUser](queryMap, updateMap) ok, rowsAffected := models.Update[models.BackUser](queryMap, updateMap)
if !ok || rowsAffected == 0 { if !ok || rowsAffected == 0 {
return false return false
@@ -111,11 +122,12 @@ func ChangePassword(changePwd map[string]interface{}) bool {
} }
newPassword := utils.PasswordEncrypt(changePwd["newPassword"].(string)) newPassword := utils.PasswordEncrypt(changePwd["newPassword"].(string))
colMap := map[string]interface{}{ colMap := map[string]interface{}{
"id": 1, "id": 1.0,
"password": newPassword, "password": newPassword,
} }
models.BeforeSave(colMap, -1) models.BeforeSave(colMap, -1)
delete(colMap, "id") delete(colMap, "id")
delete(colMap, "modify_user")
rowAffected := global.Db.Model(models.BackUser{}).Where("email = ?", changePwd["email"]).Updates(colMap).RowsAffected rowAffected := global.Db.Model(models.BackUser{}).Where("email = ?", changePwd["email"]).Updates(colMap).RowsAffected
if rowAffected == 0 { if rowAffected == 0 {
return false return false

View File

@@ -32,3 +32,9 @@ bos:
accessKey: 90dbff87c5aa4bdbb0d7a29e130b2808 accessKey: 90dbff87c5aa4bdbb0d7a29e130b2808
secretKey: e53a672a10294abc8ecabe1ef92625b1 secretKey: e53a672a10294abc8ecabe1ef92625b1
domain: bj.bcebos.com domain: bj.bcebos.com
kafka:
servers:
- myhost.fallen-angle.com:9092
topic: ncov_track
partition: 0

View File

@@ -8,7 +8,6 @@ import (
) )
func SendEmail(subject string, text string, to ...string) bool { func SendEmail(subject string, text string, to ...string) bool {
//TODO: add logs
e := email.Email{ e := email.Email{
From: "nCovTrack Server<1853633282@qq.com>", From: "nCovTrack Server<1853633282@qq.com>",
To: to, To: to,
@@ -20,6 +19,7 @@ func SendEmail(subject string, text string, to ...string) bool {
smtp.PlainAuth("", global.ServerSettings.Email.Account, global.ServerSettings.Email.Password, global.ServerSettings.Email.Host), smtp.PlainAuth("", global.ServerSettings.Email.Account, global.ServerSettings.Email.Password, global.ServerSettings.Email.Host),
) )
if err != nil { if err != nil {
fmt.Println("Send failed")
return false return false
} }
return true return true

View File

@@ -31,7 +31,11 @@ func GetWithHeader(url string, header map[string]string) string {
cost := time.Since(startTime) cost := time.Since(startTime)
var logParams []interface{} var logParams []interface{}
logParams = append(logParams, logParams = append(logParams,
"reqest", req, "reqest", map[string]interface{}{
"url": req.URL,
"method": req.Method,
"header": req.Header,
},
"cost", cost.String(), "cost", cost.String(),
) )
if err != nil { if err != nil {

View File

@@ -15,3 +15,24 @@ func Map[T any, V any](arr []T, fun func(item T) V) []V {
} }
return res return res
} }
func Distinct[T comparable](arr []T) []T {
set := map[T]interface{}{}
for _, item := range arr {
set[item] = nil
}
var res []T
for k := range set {
res = append(res, k)
}
return res
}
func Contains[T comparable](arr []T, item T) bool {
for _, a := range arr {
if a == item {
return true
}
}
return false
}

View File

@@ -1,40 +0,0 @@
package utils
type void struct{}
// This is set with generic
type Set[T comparable] struct {
setMap map[T]void
}
func NewSet[T comparable](eles ...T) *Set[T] {
set := &Set[T]{setMap: make(map[T]void)}
set.AddAll(eles...)
return set
}
func (set *Set[T]) Add(ele T) *Set[T] {
set.setMap[ele] = void{}
return set
}
func (set *Set[T]) AddAll(eles ...T) *Set[T] {
for _, ele := range eles {
set.Add(ele)
}
return set
}
func (set *Set[T]) Delete(ele T) *Set[T] {
delete(set.setMap, ele)
return set
}
func (set *Set[T]) ToSlice() []T {
var s []T
for k, _ := range set.setMap {
s = append(s, k)
}
return s
}