init repository

This commit is contained in:
yystopf 2022-02-11 18:15:10 +08:00
commit 5f7c72b365
59 changed files with 3429 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
tmp/*
.vscode/*
conf/app.ini
.idea/*
runtime/logs/*
vendor/*
config.yaml
go.sum
__debug_bin
latest_log
potato

134
README.md Normal file
View File

@ -0,0 +1,134 @@
# AccountServer
[![GitLink AccountServer](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://gitlink.org.cn/Gitlink/account-server)
账号服务使用golang微服务脚手架搭建[micro-server-simple](https://www.gitlink.org.cn/Gitlink/micro-server-simple)
## 内容列表
- [AccountServer](#accountserver)
- [内容列表](#内容列表)
- [项目结构](#项目结构)
- [安装](#安装)
- [配置说明](#配置说明)
- [使用说明](#使用说明)
- [相关仓库](#相关仓库)
- [如何贡献](#如何贡献)
- [使用许可](#使用许可)
## 项目结构
```
account-server
├── config(配置目录)
├── docs(文档集合)
├── global(全局变量)
├── initialize(初始化函数)
├── internal(内部模块)
│   ├── controller(控制器层,用于存放控制器)
│   ├── dao(数据访问层所有与数据相关等操作都会在dao层进行)
│   ├── job(后台任务)
│   ├── middleware(HTTP中间件)
│   ├── model(模型层用于存放model对象)
│   ├── routers(路由相关逻辑处理)
│   └── service(项目核心业务逻辑)
├── migrations(数据库迁移文件)
├── pkg(项目相关等模块包)
├── scripts(各类构建、按照,分析等操作等脚本)
└── tmp(项目生成的临时文件)
```
## 安装
这个项目使用 [go](https://golang.org/) 、 [swag](https://github.com/swaggo/swag)、[migrate](https://github.com/golang-migrate/migrate)等CLI工具
请确保你本地安装了它们。
go
```sh
$ tar -C /usr/local -xzf go1.4.linux-amd64.tar.gz
$ export PATH=$PATH:/usr/local/go/bin
```
swag安装
```sh
$ go get -u github.com/swaggo/swag/cmd/swag
$ mv $GOPATH/bin/swag /usr/local/go/bin
```
migrate安装
```sh
$ go get -u github.com/golang-migrate/migrate/v4/cmd/migrate
$ mv $GOPATH/bin/migrate /usr/local/go/bin
```
## 配置说明
根目录下需要有config.yaml如果没有请进行以下操作
```sh
cp config.yaml.example config.yaml
```
---
| 参数类别 | 参数名称 | 描述 |
| -------- | ----------------------- | ------------------------------------------------------------ |
| app | name | 微服务名称 |
| | version | 微服务版本号 |
| | domain | 微服务主页 |
| | run_mode | 运行模式可选debug、release、test |
| | default_context_timeout | 上下文超时时长 |
| | page_size | 默认分页数量 |
| server | http_port | http服务端口号 |
| | grpc_port | grpc服务端口号 |
| | read_timeout | 读数据超时时长 |
| | write_timeout | 写数据超时时间 |
| database | type | 数据库类型可选mysql、postgresql |
| | user | 数据库用户 |
| | password | 数据库密码 |
| | host | 数据库地址 |
| | port | 数据库端口号 |
| | name | 数据库名称 |
| | table_prefix | 数据库表前缀 |
| redis | host | redis地址 |
| | port | redis端口号 |
| | password | redis密码 |
| | db | redis实例编号 |
| zap | level | 日志级别, 可选debug、info、warn、error、dpanic、panic、fatal |
| | format | 日志输出格式可选json, console |
| | prefix | 日志前缀 |
| | director | 日志目录 |
| | link-name | 日志名称 |
| | show-line | 开启开发模式,堆栈跟踪 |
| | encode-level | 日志编码格式可选LowercaseLevelEncoder、LowercaseColorLevelEncoder、CapitalLevelEncoder、CapitalColorLevelEncoder |
| | stacktrace-key | 堆栈跟踪输出的名称 |
| | log-in-console | 是否同步日志到console |
## 使用说明
```sh
# 启动项目
$ go build -o account-server main.go
$ ./account-server
# 生成api文档
$ swag init
# 生成migrate数据库迁移
$ migrate create -ext sql -dir migrations -seq create_xxx
```
## 相关仓库
- [Gin](https://github.com/gin-gonic/gin) — Web Framework
- [Gorm](https://github.com/jinzhu/gorm) — ORM
- [Swag](https://github.com/swaggo/swag) - RESTful API Doc
- [Migrate](https://github.com/golang-migrate/migrate) - Database migrations
- [Cron](https://github.com/robfig/cron) - A cron library
## 如何贡献
非常欢迎你的加入![提一个 Issue](https://gitlink.org.cn/Gitlink/account-server/issues/new) 或者提交一个 Pull Request。
## 使用许可
[MIT]() © GitLink

35
config.yaml.example Normal file
View File

@ -0,0 +1,35 @@
app:
name: 'account-server'
version: '1.0.0'
domain: '127.0.0.1'
run_mode: 'debug'
default_context_timeout: 60
page_size: 10
server:
http_port: 8021
grpc_port: 8022
read_timeout: 60
write_timeout: 60
database:
type: 'mysql'
user: 'root'
password: '123456'
host: '127.0.0.1'
port: 3306
name: 'account-server'
table_prefix: 'm_'
redis:
host: '127.0.0.1'
port: '6379'
password: ''
db: 1
zap:
level: 'info'
format: 'console'
prefix: '[Account-Server]'
director: 'tmp/log'
link-name: 'latest_log'
show-line: true
encode-level: 'LowercaseColorLevelEncoder'
stacktrace-key: 'stacktrace'
log-in-console: true

16
config/app.go Normal file
View File

@ -0,0 +1,16 @@
/*
* @Date: 2021-03-22 09:46:19
* @LastEditors: viletyy
* @LastEditTime: 2021-06-13 23:00:46
* @FilePath: /potato/config/app.go
*/
package config
type App struct {
Name string `mapstructure:"name" json:"name" yaml:"name"`
Version string `mapstructure:"version" json:"version" yaml:"version"`
Domain string `mapstructure:"domain" json:"domain" yaml:"domain"`
PageSize int64 `mapstructure:"page_size" json:"page_size" yaml:"page_size"`
RunMode string `mapstructure:"run_mode" json:"run_mode" yaml:"run_mode"`
DefaultContextTimeout int64 `mapstructure:"default_context_timeout" json:"default_context_timeout" yaml:"default_context_timeout"`
}

15
config/config.go Normal file
View File

@ -0,0 +1,15 @@
/*
* @Date: 2021-03-22 09:45:22
* @LastEditors: viletyy
* @LastEditTime: 2021-06-12 23:07:27
* @FilePath: /potato/config/config.go
*/
package config
type Config struct {
App App `mapstructure:"app" json:"app" yaml:"app"`
Server Server `mapstructure:"server" json:"server" yaml:"server"`
Database Database `mapstructure:"database" json:"database" yaml:"database"`
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"`
}

17
config/database.go Normal file
View File

@ -0,0 +1,17 @@
/*
* @Date: 2021-03-22 09:56:48
* @LastEditors: viletyy
* @LastEditTime: 2021-03-22 10:00:26
* @FilePath: /potato/config/database.go
*/
package config
type Database struct {
Type string `mapstructure:"type" json:"type" yaml:"app"`
User string `mapstructure:"user" json:"user" yaml:"user"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
Host string `mapstructure:"host" json:"host" yaml:"host"`
Port int64 `mapstructure:"port" json:"port" yaml:"port"`
Name string `mapstructure:"name" json:"name" yaml:"name"`
TablePrefix string `mapstructure:"table_prefix" json:"table_prefix" yaml:"table_prefix"`
}

14
config/redis.go Normal file
View File

@ -0,0 +1,14 @@
/*
* @Date: 2021-03-22 10:00:42
* @LastEditors: viletyy
* @LastEditTime: 2021-03-22 10:02:39
* @FilePath: /potato/config/redis.go
*/
package config
type Redis struct {
Host string `mapstructure:"host" json:"host" yaml:"host"`
Port int64 `mapstructure:"port" json:"port" yaml:"port"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
Db int64 `mapstructure:"db" json:"db" yaml:"db"`
}

15
config/server.go Normal file
View File

@ -0,0 +1,15 @@
/*
* @Date: 2021-03-22 09:54:07
* @LastEditors: viletyy
* @LastEditTime: 2021-07-09 14:22:47
* @FilePath: /potato/config/server.go
*/
package config
type Server struct {
HttpPort int64 `mapstructure:"http_port" json:"http_port" yaml:"http_port"`
GrpcPort int64 `mapstructure:"grpc_port" json:"grpc_port" yaml:"grpc_port"`
ReadTimeout int64 `mapstructure:"read_timeout" json:"read_timeout" yaml:"read_timeout"`
WriteTimeout int64 `mapstructure:"write_timeout" json:"write_timeout" yaml:"write_timeout"`
TracerHostPort string `mapstructure:"tracer_host_port" json:"tracer_host_port" yaml:"tracer_host_port"`
}

19
config/zap.go Normal file
View File

@ -0,0 +1,19 @@
/*
* @Date: 2021-03-22 10:35:42
* @LastEditors: viletyy
* @LastEditTime: 2021-03-22 10:35:57
* @FilePath: /potato/config/zap.go
*/
package config
type Zap struct {
Level string `mapstructure:"level" json:"level" yaml:"level"`
Format string `mapstructure:"format" json:"format" yaml:"format"`
Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`
Director string `mapstructure:"director" json:"director" yaml:"director"`
LinkName string `mapstructure:"link-name" json:"linkName" yaml:"link-name"`
ShowLine bool `mapstructure:"show-line" json:"showLine" yaml:"showLine"`
EncodeLevel string `mapstructure:"encode-level" json:"encodeLevel" yaml:"encode-level"`
StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktraceKey" yaml:"stacktrace-key"`
LogInConsole bool `mapstructure:"log-in-console" json:"logInConsole" yaml:"log-in-console"`
}

288
docs/docs.go Normal file
View File

@ -0,0 +1,288 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag
package docs
import (
"bytes"
"encoding/json"
"strings"
"github.com/alecthomas/template"
"github.com/swaggo/swag"
)
var doc = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{.Description}}",
"title": "{{.Title}}",
"contact": {},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/templates": {
"get": {
"description": "一段描述",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "数据列表",
"parameters": [
{
"type": "integer",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "每页数量",
"name": "page_size",
"in": "query"
},
{
"maxLength": 100,
"type": "string",
"description": "名称搜索",
"name": "name",
"in": "query"
},
{
"type": "integer",
"description": "uuid搜索",
"name": "uuid",
"in": "query"
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
},
"post": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "新增一条模板数据",
"parameters": [
{
"maxLength": 100,
"minLength": 1,
"type": "string",
"description": "名称",
"name": "name",
"in": "formData",
"required": true
},
{
"type": "integer",
"description": "uuid",
"name": "uuid",
"in": "formData"
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
}
},
"/templates/{id}": {
"get": {
"description": "这是一段描述",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "获取单个模板",
"parameters": [
{
"type": "integer",
"description": "ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
},
"delete": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "删除一条数据",
"parameters": [
{
"type": "integer",
"description": "ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
},
"patch": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "修改模板数据",
"parameters": [
{
"type": "integer",
"description": "ID",
"name": "id",
"in": "path",
"required": true
},
{
"maxLength": 100,
"minLength": 1,
"type": "string",
"description": "名称",
"name": "name",
"in": "formData"
},
{
"type": "integer",
"description": "uuid",
"name": "uuid",
"in": "formData"
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
}
}
},
"definitions": {
"model.Template": {
"type": "object",
"properties": {
"created_at": {
"type": "string"
},
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"uuid": {
"type": "integer"
}
}
}
}
}`
type swaggerInfo struct {
Version string
Host string
BasePath string
Schemes []string
Title string
Description string
}
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{
Version: "1.0",
Host: "",
BasePath: "/api",
Schemes: []string{},
Title: "AccountServer Api",
Description: "账号服务",
}
type s struct{}
func (s *s) ReadDoc() string {
sInfo := SwaggerInfo
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
t, err := template.New("swagger_info").Funcs(template.FuncMap{
"marshal": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
},
}).Parse(doc)
if err != nil {
return doc
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, sInfo); err != nil {
return doc
}
return tpl.String()
}
func init() {
swag.Register(swag.Name, &s{})
}

225
docs/swagger.json Normal file
View File

@ -0,0 +1,225 @@
{
"swagger": "2.0",
"info": {
"description": "账号服务",
"title": "AccountServer Api",
"contact": {},
"version": "1.0"
},
"basePath": "/api",
"paths": {
"/templates": {
"get": {
"description": "一段描述",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "数据列表",
"parameters": [
{
"type": "integer",
"description": "页码",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "每页数量",
"name": "page_size",
"in": "query"
},
{
"maxLength": 100,
"type": "string",
"description": "名称搜索",
"name": "name",
"in": "query"
},
{
"type": "integer",
"description": "uuid搜索",
"name": "uuid",
"in": "query"
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
},
"post": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "新增一条模板数据",
"parameters": [
{
"maxLength": 100,
"minLength": 1,
"type": "string",
"description": "名称",
"name": "name",
"in": "formData",
"required": true
},
{
"type": "integer",
"description": "uuid",
"name": "uuid",
"in": "formData"
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
}
},
"/templates/{id}": {
"get": {
"description": "这是一段描述",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "获取单个模板",
"parameters": [
{
"type": "integer",
"description": "ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
},
"delete": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "删除一条数据",
"parameters": [
{
"type": "integer",
"description": "ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
},
"patch": {
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"tags": [
"templates"
],
"summary": "修改模板数据",
"parameters": [
{
"type": "integer",
"description": "ID",
"name": "id",
"in": "path",
"required": true
},
{
"maxLength": 100,
"minLength": 1,
"type": "string",
"description": "名称",
"name": "name",
"in": "formData"
},
{
"type": "integer",
"description": "uuid",
"name": "uuid",
"in": "formData"
}
],
"responses": {
"200": {
"description": "请求成功",
"schema": {
"$ref": "#/definitions/model.Template"
}
}
}
}
}
},
"definitions": {
"model.Template": {
"type": "object",
"properties": {
"created_at": {
"type": "string"
},
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"uuid": {
"type": "integer"
}
}
}
}
}

149
docs/swagger.yaml Normal file
View File

@ -0,0 +1,149 @@
basePath: /api
definitions:
model.Template:
properties:
created_at:
type: string
id:
type: integer
name:
type: string
updated_at:
type: string
uuid:
type: integer
type: object
info:
contact: {}
description: 账号服务
title: AccountServer Api
version: "1.0"
paths:
/templates:
get:
consumes:
- application/json
description: 一段描述
parameters:
- description: 页码
in: query
name: page
type: integer
- description: 每页数量
in: query
name: page_size
type: integer
- description: 名称搜索
in: query
maxLength: 100
name: name
type: string
- description: uuid搜索
in: query
name: uuid
type: integer
produces:
- application/json
responses:
"200":
description: 请求成功
schema:
$ref: '#/definitions/model.Template'
summary: 数据列表
tags:
- templates
post:
consumes:
- multipart/form-data
parameters:
- description: 名称
in: formData
maxLength: 100
minLength: 1
name: name
required: true
type: string
- description: uuid
in: formData
name: uuid
type: integer
produces:
- application/json
responses:
"200":
description: 请求成功
schema:
$ref: '#/definitions/model.Template'
summary: 新增一条模板数据
tags:
- templates
/templates/{id}:
delete:
consumes:
- application/json
parameters:
- description: ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: 请求成功
schema:
$ref: '#/definitions/model.Template'
summary: 删除一条数据
tags:
- templates
get:
consumes:
- application/json
description: 这是一段描述
parameters:
- description: ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: 请求成功
schema:
$ref: '#/definitions/model.Template'
summary: 获取单个模板
tags:
- templates
patch:
consumes:
- multipart/form-data
parameters:
- description: ID
in: path
name: id
required: true
type: integer
- description: 名称
in: formData
maxLength: 100
minLength: 1
name: name
type: string
- description: uuid
in: formData
name: uuid
type: integer
produces:
- application/json
responses:
"200":
description: 请求成功
schema:
$ref: '#/definitions/model.Template'
summary: 修改模板数据
tags:
- templates
swagger: "2.0"

23
global/global.go Normal file
View File

@ -0,0 +1,23 @@
/*
* @Date: 2021-03-22 09:42:09
* @LastEditors: viletyy
* @LastEditTime: 2021-06-13 23:53:51
* @FilePath: /potato/global/global.go
*/
package global
import (
"github.com/go-redis/redis"
"github.com/jinzhu/gorm"
"github.com/spf13/viper"
"gitlink.org.cn/Gitlink/account-server/config"
"go.uber.org/zap"
)
var (
GO_DB *gorm.DB
GO_REDIS *redis.Client
GO_CONFIG *config.Config
GO_VP *viper.Viper
GO_LOG *zap.Logger
)

36
go.mod Normal file
View File

@ -0,0 +1,36 @@
module gitlink.org.cn/Gitlink/account-server
go 1.15
require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/eddycjy/opentracing-gorm v0.0.0-20200209122056-516a807d2182
github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.7.7
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/go-playground/validator/v10 v10.6.1
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang-migrate/migrate/v4 v4.15.1
github.com/golang/protobuf v1.5.2
github.com/jinzhu/gorm v1.9.16
github.com/kr/text v0.2.0 // indirect
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/lestrrat-go/strftime v1.0.4 // indirect
github.com/lib/pq v1.10.0
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/onsi/gomega v1.13.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/robfig/cron/v3 v3.0.0
github.com/smacker/opentracing-gorm v0.0.0-20181207094635-cd4974441042 // indirect
github.com/spf13/viper v1.7.1
github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.0
github.com/viletyy/yolk v1.0.1
go.uber.org/atomic v1.8.0 // indirect
go.uber.org/zap v1.17.0
google.golang.org/grpc v1.41.0
google.golang.org/protobuf v1.27.1
)

22
initialize/cron.go Normal file
View File

@ -0,0 +1,22 @@
/*
* @Date: 2021-07-08 13:54:38
* @LastEditors: viletyy
* @LastEditTime: 2021-07-08 14:01:18
* @FilePath: /potato/initialize/cron.go
*/
package initialize
import (
"github.com/robfig/cron/v3"
"gitlink.org.cn/Gitlink/account-server/internal/job"
)
func Cron() {
c := cron.New()
c.AddJob("* * * * *", job.TestJob{})
c.Start()
select {}
}

73
initialize/gorm.go Normal file
View File

@ -0,0 +1,73 @@
/*
* @Date: 2021-03-22 10:12:38
* @LastEditors: viletyy
* @LastEditTime: 2021-07-09 14:27:45
* @FilePath: /potato/initialize/gorm.go
*/
package initialize
import (
"fmt"
otgorm "github.com/eddycjy/opentracing-gorm"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/internal/model"
)
func Gorm() *gorm.DB {
switch global.GO_CONFIG.Database.Type {
case "mysql":
return GormMysql()
case "postgresql":
return GormPostgresql()
default:
return GormMysql()
}
}
func GormMysql() *gorm.DB {
db, err := gorm.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", global.GO_CONFIG.Database.User, global.GO_CONFIG.Database.Password, global.GO_CONFIG.Database.Host, global.GO_CONFIG.Database.Port, global.GO_CONFIG.Database.Name))
if err != nil {
global.GO_LOG.Error(fmt.Sprintf("Mysql Gorm Open Error: %v", err))
}
GormSet(db)
return db
}
func GormPostgresql() *gorm.DB {
db, err := gorm.Open("postgres", fmt.Sprintf("host=%s user=%s dbname=%s port=%d sslmode=disable password=%s", global.GO_CONFIG.Database.Host, global.GO_CONFIG.Database.User, global.GO_CONFIG.Database.Name, global.GO_CONFIG.Database.Port, global.GO_CONFIG.Database.Password))
if err != nil {
global.GO_LOG.Error(fmt.Sprintf("Postgresql Gorm Open Error: %v", err))
}
GormSet(db)
return db
}
func GormSet(db *gorm.DB) {
// 设置表前缀
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return global.GO_CONFIG.Database.TablePrefix + defaultTableName
}
// 设置日志
if global.GO_CONFIG.App.RunMode == "debug" {
db.LogMode(true)
}
// 设置迁移
db.AutoMigrate(
&model.Template{},
)
// 设置空闲连接池中的最大连接数
db.DB().SetMaxIdleConns(10)
// 设置打开数据库连接的最大数量
db.DB().SetMaxOpenConns(100)
// 设置链路追踪
otgorm.AddGormCallbacks(db)
}

29
initialize/grpc_server.go Normal file
View File

@ -0,0 +1,29 @@
/*
* @Date: 2021-06-17 00:19:32
* @LastEditors: viletyy
* @LastEditTime: 2021-07-09 14:52:03
* @FilePath: /potato/initialize/grpc_server.go
*/
package initialize
import (
"net"
pb "gitlink.org.cn/Gitlink/account-server/proto"
grpc_server "gitlink.org.cn/Gitlink/account-server/server"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
func RunGrpcServer(port string) error {
server := grpc.NewServer()
pb.RegisterTemplateServiceServer(server, grpc_server.NewTemplateServer())
reflection.Register(server)
lis, err := net.Listen("tcp", ":"+port)
if err != nil {
return err
}
return server.Serve(lis)
}

29
initialize/http_server.go Normal file
View File

@ -0,0 +1,29 @@
/*
* @Date: 2021-03-22 17:03:27
* @LastEditors: viletyy
* @LastEditTime: 2021-07-09 14:24:36
* @FilePath: /potato/initialize/http_server.go
*/
package initialize
import (
"fmt"
"net/http"
"time"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/internal/routers"
)
func RunHttpServer(port string) error {
router := routers.InitRouter()
server := &http.Server{
Addr: fmt.Sprintf(":%s", port),
Handler: router,
ReadTimeout: time.Duration(global.GO_CONFIG.Server.ReadTimeout) * time.Second,
WriteTimeout: time.Duration(global.GO_CONFIG.Server.WriteTimeout) * time.Second,
MaxHeaderBytes: 1 << 20,
}
return server.ListenAndServe()
}

67
initialize/migrate.go Normal file
View File

@ -0,0 +1,67 @@
package initialize
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
migrate "github.com/golang-migrate/migrate/v4"
migrate_mysql "github.com/golang-migrate/migrate/v4/database/mysql"
migrate_postgres "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
_ "github.com/lib/pq"
"gitlink.org.cn/Gitlink/account-server/global"
)
func Migrate() {
switch global.GO_CONFIG.Database.Type {
case "mysql":
MigrateSetMysql()
return
case "postgresql":
MigrateSetPostgresql()
return
default:
MigrateSetMysql()
return
}
}
func MigrateSetPostgresql() {
db, err := sql.Open("postgres", fmt.Sprintf("%s:%s@(%s:%d)/%s?sslmode=enable", global.GO_CONFIG.Database.User, global.GO_CONFIG.Database.Password, global.GO_CONFIG.Database.Host, global.GO_CONFIG.Database.Port, global.GO_CONFIG.Database.Name))
if err != nil {
global.GO_LOG.Error(fmt.Sprintf("sql.Open: %v", err))
}
driver, err := migrate_postgres.WithInstance(db, &migrate_postgres.Config{})
if err != nil {
global.GO_LOG.Error(fmt.Sprintf("migrate_postgres.WithInstance: %v", err))
}
m, err := migrate.NewWithDatabaseInstance(
"files:///migrations",
"postgres", driver)
if err != nil {
global.GO_LOG.Error(fmt.Sprintf("migrate.NewWithDatabaseInstance: %v", err))
}
m.Up()
// m.Down()
}
func MigrateSetMysql() {
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s?multiStatements=true", global.GO_CONFIG.Database.User, global.GO_CONFIG.Database.Password, global.GO_CONFIG.Database.Host, global.GO_CONFIG.Database.Port, global.GO_CONFIG.Database.Name))
if err != nil {
global.GO_LOG.Fatal(fmt.Sprintf("sql.Open: %v", err))
}
driver, err := migrate_mysql.WithInstance(db, &migrate_mysql.Config{})
if err != nil {
global.GO_LOG.Fatal(fmt.Sprintf("migrate_mysql.WithInstance: %v", err))
}
m, err := migrate.NewWithDatabaseInstance(
"file://migrations",
"migrate", driver)
if err != nil {
global.GO_LOG.Fatal(fmt.Sprintf("migrate.NewWithDatabaseInstance: %v", err))
}
m.Up()
// m.Down()
}

32
initialize/redis.go Normal file
View File

@ -0,0 +1,32 @@
/*
* @Date: 2021-03-22 10:12:42
* @LastEditors: viletyy
* @LastEditTime: 2021-03-23 09:26:11
* @FilePath: /potato/initialize/redis.go
*/
package initialize
import (
"fmt"
"github.com/go-redis/redis"
"gitlink.org.cn/Gitlink/account-server/global"
)
func Redis() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.GO_CONFIG.Redis.Host, global.GO_CONFIG.Redis.Port),
Password: global.GO_CONFIG.Redis.Password,
DB: int(global.GO_CONFIG.Redis.Db),
})
RedisSet(rdb)
return rdb
}
func RedisSet(rdb *redis.Client) {
_, pingErr := rdb.Ping().Result()
if pingErr != nil {
global.GO_LOG.Error(fmt.Sprintf("Redis Connection Error: %v", pingErr))
}
}

175
initialize/viper.go Normal file
View File

@ -0,0 +1,175 @@
/*
* @Date: 2021-03-22 09:38:24
* @LastEditors: viletyy
* @LastEditTime: 2021-03-22 10:12:33
* @FilePath: /potato/initialize/viper.go
*/
package initialize
import (
"fmt"
"os"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"github.com/viletyy/yolk/convert"
"gitlink.org.cn/Gitlink/account-server/global"
)
func Viper() *viper.Viper {
v := viper.New()
v.SetConfigFile("config.yaml")
err := v.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed:", e.Name)
if err := v.Unmarshal(&global.GO_CONFIG); err != nil {
fmt.Println(err)
}
})
if err := v.Unmarshal(&global.GO_CONFIG); err != nil {
fmt.Println(err)
}
loadEnvConfig()
return v
}
func loadEnvConfig() {
if os.Getenv("APP_NAME") != "" {
global.GO_CONFIG.App.Name = os.Getenv("APP_NAME")
}
if os.Getenv("APP_VERSION") != "" {
global.GO_CONFIG.App.Version = os.Getenv("APP_VERSION")
}
if os.Getenv("APP_DOMAIN") != "" {
global.GO_CONFIG.App.Domain = os.Getenv("APP_DOMAIN")
}
if os.Getenv("APP_RUN_MODE") != "" {
global.GO_CONFIG.App.RunMode = os.Getenv("APP_RUN_MODE")
}
app_default_context_timeout, _ := convert.StrTo(os.Getenv("APP_DEFAULT_CONTEXT_TIMEOUT")).Int64()
if app_default_context_timeout > 0 {
global.GO_CONFIG.App.DefaultContextTimeout = app_default_context_timeout
}
app_page_size, _ := convert.StrTo(os.Getenv("APP_PAGE_SISE")).Int64()
if app_page_size > 0 {
global.GO_CONFIG.App.PageSize = app_page_size
}
server_http_port, _ := convert.StrTo(os.Getenv("SERVER_HTTP_PORT")).Int64()
if server_http_port > 0 {
global.GO_CONFIG.Server.HttpPort = server_http_port
}
server_grpc_port, _ := convert.StrTo(os.Getenv("SERVER_GRPC_PORT")).Int64()
if server_grpc_port > 0 {
global.GO_CONFIG.Server.GrpcPort = server_grpc_port
}
server_read_timeout, _ := convert.StrTo(os.Getenv("SERVER_READ_TIMEOUT")).Int64()
if server_read_timeout > 0 {
global.GO_CONFIG.Server.ReadTimeout = server_read_timeout
}
server_write_timeout, _ := convert.StrTo(os.Getenv("SERVER_WRITE_TIMEOUT")).Int64()
if server_write_timeout > 0 {
global.GO_CONFIG.Server.WriteTimeout = server_write_timeout
}
if os.Getenv("DATABASE_TYPE") != "" {
global.GO_CONFIG.Database.Type = os.Getenv("DATABASE_TYPE")
}
if os.Getenv("DATABASE_USER") != "" {
global.GO_CONFIG.Database.User = os.Getenv("DATABASE_USER")
}
if os.Getenv("DATABASE_PASSWORD") != "" {
global.GO_CONFIG.Database.Password = os.Getenv("DATABASE_PASSWORD")
}
if os.Getenv("DATABASE_HOST") != "" {
global.GO_CONFIG.Database.Host = os.Getenv("DATABASE_HOST")
}
database_port, _ := convert.StrTo(os.Getenv("DATABASE_PORT")).Int64()
if database_port > 0 {
global.GO_CONFIG.Database.Port = database_port
}
if os.Getenv("DATABASE_NAME") != "" {
global.GO_CONFIG.Database.Name = os.Getenv("DATABASE_NAME")
}
if os.Getenv("DATABASE_TABLE_PREFIX") != "" {
global.GO_CONFIG.Database.TablePrefix = os.Getenv("DATABASE_TABLE_PREFIX")
}
if os.Getenv("REDIS_HOST") != "" {
global.GO_CONFIG.Redis.Host = os.Getenv("REDIS_HOST")
}
redis_port, _ := convert.StrTo(os.Getenv("REDIS_PORT")).Int64()
if redis_port > 0 {
global.GO_CONFIG.Redis.Port = redis_port
}
if os.Getenv("REDIS_PASSWORD") != "" {
global.GO_CONFIG.Redis.Password = os.Getenv("REDIS_PASSWORD")
}
redis_db, _ := convert.StrTo(os.Getenv("REDIS_DB")).Int64()
if redis_db > 0 {
global.GO_CONFIG.Redis.Db = redis_db
}
if os.Getenv("ZAP_LEVEL") != "" {
global.GO_CONFIG.Zap.Level = os.Getenv("ZAP_LEVEL")
}
if os.Getenv("ZAP_FORMAT") != "" {
global.GO_CONFIG.Zap.Format = os.Getenv("ZAP_FORMAT")
}
if os.Getenv("ZAP_PREFIX") != "" {
global.GO_CONFIG.Zap.Prefix = os.Getenv("ZAP_PREFIX")
}
if os.Getenv("ZAP_DIRECTOR") != "" {
global.GO_CONFIG.Zap.Director = os.Getenv("ZAP_DIRECTOR")
}
if os.Getenv("ZAP_LINK_NAME") != "" {
global.GO_CONFIG.Zap.LinkName = os.Getenv("ZAP_LINK_NAME")
}
zap_show_line, _ := convert.StrTo(os.Getenv("LOG_IN_CONSOLE")).Bool()
if !zap_show_line {
global.GO_CONFIG.Zap.ShowLine = zap_show_line
}
if os.Getenv("ZAP_ENCODE_LEVEL") != "" {
global.GO_CONFIG.Zap.EncodeLevel = os.Getenv("ZAP_ENCODE_LEVEL")
}
if os.Getenv("ZAP_STACKTRACE_KEY") != "" {
global.GO_CONFIG.Zap.StacktraceKey = os.Getenv("ZAP_STACKTRACE_KEY")
}
zap_log_in_console, _ := convert.StrTo(os.Getenv("LOG_IN_CONSOLE")).Bool()
if !zap_log_in_console {
global.GO_CONFIG.Zap.LogInConsole = zap_log_in_console
}
}

105
initialize/zap.go Normal file
View File

@ -0,0 +1,105 @@
/*
* @Date: 2021-03-22 10:13:04
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 15:44:06
* @FilePath: /potato/initialize/zap.go
*/
package initialize
import (
"fmt"
"time"
"github.com/viletyy/yolk/directory"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/pkg"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var level zapcore.Level
func Zap() (logger *zap.Logger) {
if err := directory.CreateDir(global.GO_CONFIG.Zap.Director); err != nil {
fmt.Printf("Create Zap Dir err:%v", err.Error())
}
switch global.GO_CONFIG.Zap.Level {
case "debug":
level = zap.DebugLevel
case "info":
level = zap.InfoLevel
case "warn":
level = zap.WarnLevel
case "error":
level = zap.ErrorLevel
case "dpanic":
level = zap.DPanicLevel
case "panic":
level = zap.PanicLevel
case "fatal":
level = zap.FatalLevel
default:
level = zap.InfoLevel
}
if level == zap.DebugLevel || level == zap.ErrorLevel {
logger = zap.New(getEncoderCore(), zap.AddStacktrace(level))
} else {
logger = zap.New(getEncoderCore())
}
if global.GO_CONFIG.Zap.ShowLine {
logger = logger.WithOptions(zap.AddCaller())
}
return logger
}
func getEncoderCore() (core zapcore.Core) {
writer, err := pkg.GetWriteSyncer() // 使用file-rotatelogs进行日志分割
if err != nil {
fmt.Printf("Get Write Syncer Failed err: %v", err.Error())
return
}
return zapcore.NewCore(getEncoder(), writer, level)
}
func getEncoder() zapcore.Encoder {
if global.GO_CONFIG.Zap.Format == "json" {
return zapcore.NewJSONEncoder(getEncoderConfig())
}
return zapcore.NewConsoleEncoder(getEncoderConfig())
}
func getEncoderConfig() (config zapcore.EncoderConfig) {
config = zapcore.EncoderConfig{
MessageKey: "message",
LevelKey: "level",
TimeKey: "time",
NameKey: "logger",
CallerKey: "caller",
StacktraceKey: global.GO_CONFIG.Zap.StacktraceKey,
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: CustomTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.FullCallerEncoder,
}
switch {
case global.GO_CONFIG.Zap.EncodeLevel == "LowercaseLevelEncoder": // 小写编码器(默认)
config.EncodeLevel = zapcore.LowercaseLevelEncoder
case global.GO_CONFIG.Zap.EncodeLevel == "LowercaseColorLevelEncoder": // 小写编码器带颜色
config.EncodeLevel = zapcore.LowercaseColorLevelEncoder
case global.GO_CONFIG.Zap.EncodeLevel == "CapitalLevelEncoder": // 大写编码器
config.EncodeLevel = zapcore.CapitalLevelEncoder
case global.GO_CONFIG.Zap.EncodeLevel == "CapitalColorLevelEncoder": // 大写编码器带颜色
config.EncodeLevel = zapcore.CapitalColorLevelEncoder
default:
config.EncodeLevel = zapcore.LowercaseLevelEncoder
}
return config
}
func CustomTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format(global.GO_CONFIG.Zap.Prefix + "2006/01/02 - 15:04:05.000"))
}

View File

@ -0,0 +1,199 @@
package api
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"github.com/viletyy/yolk/convert"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/internal/service"
"gitlink.org.cn/Gitlink/account-server/pkg/app"
"gitlink.org.cn/Gitlink/account-server/pkg/errcode"
)
type Template struct{}
func NewTemplate() Template {
return Template{}
}
// @Summary 数据列表
// @Tags templates
// @Description 一段描述
// @Accept json
// @Produce json
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Param name query string false "名称搜索" maxlength(100)
// @Param uuid query int false "uuid搜索"
// @Success 200 {object} model.Template "请求成功"
// @Router /templates [get]
func (template Template) List(c *gin.Context) {
param := service.TemplateListRequest{}
response := app.NewResponse(c)
valid, errs := app.BindAndValid(c, &param)
if !valid {
global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs)
response.ToResponseErrors(errs.Errors())
return
}
svc := service.New(c.Request.Context())
paper := app.Pager{Page: app.GetPage(c), PageSize: app.GetPageSize(c)}
total, err := svc.CountTemplate(&service.CountTemplateRequest{Name: param.Name, Uuid: param.Uuid})
if err != nil {
global.GO_LOG.Sugar().Errorf("svc.CountTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorCountFail)
return
}
templates, err := svc.GetTemplateList(&param, &paper)
if err != nil {
global.GO_LOG.Sugar().Errorf("svc.GetTemplateList err: %v", err)
response.ToErrorResponse(errcode.ErrorGetListFail)
return
}
response.ToResponseList(templates, total)
}
// @Summary 获取单个模板
// @Tags templates
// @Description 这是一段描述
// @Accept json
// @Produce json
// @Param id path int true "ID"
// @Success 200 {object} model.Template "请求成功"
// @Router /templates/{id} [get]
func (template Template) Get(c *gin.Context) {
templateID, err := convert.StrTo(c.Param("id")).Int64()
response := app.NewResponse(c)
if err != nil {
global.GO_LOG.Sugar().Errorf("convert.StrTo err: %v", err)
response.ToErrorResponse(errcode.InvalidParams)
return
}
param := service.TemplateRequest{ID: templateID}
valid, errs := app.BindAndValid(c, &param)
if !valid {
global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs)
response.ToResponseErrors(errs.Errors())
return
}
svc := service.New(c.Request.Context())
dbTemplate, err := svc.GetTemplate(&param)
if err != nil {
global.GO_LOG.Sugar().Errorf("svc.GetTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorGetFail)
return
}
response.ToResponse(dbTemplate)
}
// @Summary 新增一条模板数据
// @Tags templates
// @Description
// @Accept mpfd
// @Produce json
// @Param name formData string true "名称" minlength(1) maxlength(100)
// @Param uuid formData int false "uuid"
// @Success 200 {object} model.Template "请求成功"
// @Router /templates [post]
func (template Template) Create(c *gin.Context) {
param := service.CreateTemplateRequest{}
response := app.NewResponse(c)
valid, errs := app.BindAndValid(c, &param)
if !valid {
global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs)
response.ToResponseErrors(errs.Errors())
return
}
svc := service.New(c.Request.Context())
dbTemplate, err := svc.CreateTemplate(&param)
if err != nil {
global.GO_LOG.Sugar().Errorf("svc.CreateTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorCreateFail)
return
}
response.ToResponse(dbTemplate)
}
// @Summary 修改模板数据
// @Tags templates
// @Description
// @Accept mpfd
// @Produce json
// @Param id path int true "ID"
// @Param name formData string false "名称" minlength(1) maxlength(100)
// @Param uuid formData int false "uuid"
// @Success 200 {object} model.Template "请求成功"
// @Router /templates/{id} [patch]
func (template Template) Update(c *gin.Context) {
templateID, err := convert.StrTo(c.Param("id")).Int64()
response := app.NewResponse(c)
if err != nil {
global.GO_LOG.Sugar().Errorf("convert.StrTo err: %v", err)
response.ToErrorResponse(errcode.InvalidParams)
return
}
param := service.UpdateTemplateRequest{ID: templateID}
valid, errs := app.BindAndValid(c, &param)
if !valid {
global.GO_LOG.Sugar().Errorf("app.BindAndValid errs: %v", errs)
response.ToResponseErrors(errs)
return
}
svc := service.New(c.Request.Context())
dbTemplate, err := svc.UpdateTemplate(&param)
if err != nil {
if err == gorm.ErrRecordNotFound {
global.GO_LOG.Sugar().Errorf("svc.UpdateTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorGetFail)
return
} else {
global.GO_LOG.Sugar().Errorf("svc.UpdateTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorUpdateFail)
return
}
}
response.ToResponse(dbTemplate)
}
// @Summary 删除一条数据
// @Tags templates
// @Description
// @Accept json
// @Produce json
// @Param id path int true "ID"
// @Success 200 {object} model.Template "请求成功"
// @Router /templates/{id} [delete]
func (template Template) Delete(c *gin.Context) {
templateId, err := convert.StrTo(c.Param("id")).Int64()
response := app.NewResponse(c)
if err != nil {
global.GO_LOG.Sugar().Errorf("convert.StrTo err: %v", err)
response.ToErrorResponse(errcode.InvalidParams)
return
}
param := service.DeleteTemplateRequest{ID: templateId}
svc := service.New(c.Request.Context())
dbTemplate, err := svc.DeleteTemplate(&param)
if err != nil {
if err == gorm.ErrRecordNotFound {
global.GO_LOG.Sugar().Errorf("svc.DeleteTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorGetFail)
return
} else {
global.GO_LOG.Sugar().Errorf("svc.DeleteTemplate err: %v", err)
response.ToErrorResponse(errcode.ErrorDeleteFail)
return
}
}
errcode.Success.Data = dbTemplate
response.ToErrorResponse(errcode.Success)
}

17
internal/dao/dao.go Normal file
View File

@ -0,0 +1,17 @@
/*
* @Date: 2021-06-10 18:46:10
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 18:48:41
* @FilePath: /potato/internal/dao/auth.go
*/
package dao
import "github.com/jinzhu/gorm"
type Dao struct {
Engine *gorm.DB
}
func New(engine *gorm.DB) *Dao {
return &Dao{Engine: engine}
}

64
internal/dao/template.go Normal file
View File

@ -0,0 +1,64 @@
package dao
import (
"gitlink.org.cn/Gitlink/account-server/internal/model"
"gitlink.org.cn/Gitlink/account-server/pkg/app"
)
func (d *Dao) CountTemplate(name string, uuid int) (int, error) {
template := model.Template{Name: name, Uuid: uuid}
return template.Count(d.Engine)
}
func (d *Dao) GetTemplateList(name string, uuid int, page, pageSize int) ([]model.Template, error) {
template := model.Template{Name: name, Uuid: uuid}
pageOffset := app.GetPageOffset(page, pageSize)
return template.List(d.Engine, pageOffset, pageSize)
}
func (d *Dao) GetTemplate(id int64) (model.Template, error) {
template := model.Template{
Model: &model.Model{ID: id},
}
return template.Get(d.Engine)
}
func (d *Dao) CreateTemplate(name string, uuid int) (model.Template, error) {
template := model.Template{
Name: name,
Uuid: uuid,
}
return template, template.Create(d.Engine)
}
func (d *Dao) UpdateTemplate(id int64, name string, uuid int) (model.Template, error) {
template := model.Template{
Name: name,
Uuid: uuid,
Model: &model.Model{ID: id},
}
dbTemplate, err := template.Get(d.Engine)
if err != nil {
return template, err
}
return dbTemplate, dbTemplate.Update(d.Engine)
}
func (d *Dao) DeleteTemplate(id int64) (model.Template, error) {
template := model.Template{
Model: &model.Model{ID: id},
}
dbTemplate, err := template.Get(d.Engine)
if err != nil {
return template, err
}
return dbTemplate, dbTemplate.Delete(d.Engine)
}

15
internal/job/test_job.go Normal file
View File

@ -0,0 +1,15 @@
/*
* @Date: 2021-07-08 14:01:46
* @LastEditors: viletyy
* @LastEditTime: 2021-07-08 14:02:36
* @FilePath: /potato/internal/job/test_job.go
*/
package job
import "fmt"
type TestJob struct{}
func (t TestJob) Run() {
fmt.Println("i'm test job")
}

View File

@ -0,0 +1,52 @@
/*
* @Date: 2021-06-12 21:55:50
* @LastEditors: viletyy
* @LastEditTime: 2021-06-14 21:00:47
* @FilePath: /potato/internal/middleware/access_log.go
*/
package middleware
import (
"bytes"
"time"
"github.com/gin-gonic/gin"
"gitlink.org.cn/Gitlink/account-server/global"
"go.uber.org/zap"
)
type AccessLogWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w AccessLogWriter) Write(p []byte) (int, error) {
if n, err := w.body.Write(p); err != nil {
return n, err
}
return w.ResponseWriter.Write(p)
}
func AccessLog() gin.HandlerFunc {
return func(c *gin.Context) {
bodyWriter := &AccessLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = bodyWriter
beginTime := time.Now().Unix()
c.Next()
endTime := time.Now().Unix()
global.GO_LOG.With(
zap.String("request", c.Request.PostForm.Encode()),
zap.String("response", bodyWriter.body.String()),
zap.String("trace_id", c.GetString("X-Trace-ID")),
zap.String("span_id", c.GetString("X-Span-ID")),
).Sugar().Infof("access log: method: %s, status_code: %d, begin_time: %d, end_time: %d",
c.Request.Method,
bodyWriter.Status(),
beginTime,
endTime,
)
}
}

View File

@ -0,0 +1,20 @@
/*
* @Date: 2021-06-13 22:01:30
* @LastEditors: viletyy
* @LastEditTime: 2021-06-13 22:02:41
* @FilePath: /potato/internal/middleware/app_info.go
*/
package middleware
import (
"github.com/gin-gonic/gin"
"gitlink.org.cn/Gitlink/account-server/global"
)
func AppInfo() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("app_name", global.GO_CONFIG.App.Name)
c.Set("app_version", global.GO_CONFIG.App.Version)
c.Next()
}
}

View File

@ -0,0 +1,24 @@
/*
* @Date: 2021-06-13 22:35:30
* @LastEditors: viletyy
* @LastEditTime: 2021-06-13 22:37:09
* @FilePath: /potato/internal/middleware/context_timeout.go
*/
package middleware
import (
"context"
"time"
"github.com/gin-gonic/gin"
)
func ContextTimeout(t time.Duration) func(c *gin.Context) {
return func(c *gin.Context) {
ctx, cancel := context.WithTimeout(c.Request.Context(), t)
defer cancel()
c.Request = c.Request.WithContext(ctx)
c.Next()
}
}

View File

@ -0,0 +1,25 @@
/*
* @Date: 2021-03-21 19:54:57
* @LastEditors: viletyy
* @LastEditTime: 2021-03-22 17:45:44
* @FilePath: /potato/middleware/cors.go
*/
package middleware
import "github.com/gin-gonic/gin"
func CORS() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}

View File

@ -0,0 +1,50 @@
/*
* @Date: 2021-03-21 19:54:57
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 21:49:20
* @FilePath: /potato/internal/middleware/jwt.go
*/
package middleware
import (
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt"
"gitlink.org.cn/Gitlink/account-server/pkg/app"
"gitlink.org.cn/Gitlink/account-server/pkg/errcode"
)
func JWT() gin.HandlerFunc {
return func(c *gin.Context) {
var (
token string
ecode = errcode.Success
)
if s, exist := c.GetQuery("token"); exist {
token = s
} else {
token = c.GetHeader("token")
}
if token == "" {
ecode = errcode.InvalidParams
} else {
_, err := app.ParseToken(token)
if err != nil {
switch err.(*jwt.ValidationError).Errors {
case jwt.ValidationErrorExpired:
ecode = errcode.UnauthorizedTokenTimeout
default:
ecode = errcode.UnauthorizedTokenError
}
}
}
if ecode != errcode.Success {
response := app.NewResponse(c)
response.ToErrorResponse(ecode)
c.Abort()
return
}
c.Next()
}
}

View File

@ -0,0 +1,45 @@
/*
* @Date: 2021-06-10 18:02:35
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 18:19:12
* @FilePath: /potato/internal/middleware/translations.go
*/
package middleware
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
"github.com/go-playground/validator/v10"
ut "github.com/go-playground/universal-translator"
enTranslations "github.com/go-playground/validator/v10/translations/en"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)
func Translations() gin.HandlerFunc {
return func(c *gin.Context) {
uni := ut.New(en.New(), zh.New())
locale := c.GetHeader("locale")
trans, _ := uni.GetTranslator(locale)
v, ok := binding.Validator.Engine().(*validator.Validate)
v.SetTagName("validate")
if ok {
switch locale {
case "zh":
_ = zhTranslations.RegisterDefaultTranslations(v, trans)
break
case "en":
_ = enTranslations.RegisterDefaultTranslations(v, trans)
break
default:
_ = zhTranslations.RegisterDefaultTranslations(v, trans)
break
}
c.Set("trans", trans)
}
c.Next()
}
}

16
internal/model/model.go Normal file
View File

@ -0,0 +1,16 @@
/*
* @Date: 2021-03-22 17:50:15
* @LastEditors: viletyy
* @LastEditTime: 2021-06-14 22:51:58
* @FilePath: /potato/internal/model/model.go
*/
package model
import "time"
type Model struct {
ID int64 `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `gorm:"index" json:"-"`
}

View File

@ -0,0 +1,71 @@
/*
* @Date: 2021-03-21 19:54:57
* @LastEditors: viletyy
* @LastEditTime: 2021-06-11 11:01:28
* @FilePath: /potato/internal/model/basic/vendor.go
*/
package model
import (
"github.com/jinzhu/gorm"
)
type Template struct {
*Model
Name string `json:"name"`
Uuid int `json:"uuid"`
}
func (v Template) Count(db *gorm.DB) (int, error) {
var count int
if v.Name != "" {
db = db.Where("name = ?", v.Name)
}
if v.Uuid != 0 {
db = db.Where("uuid = ?", v.Uuid)
}
if err := db.Model(&v).Count(&count).Error; err != nil {
return 0, err
}
return count, nil
}
func (v Template) List(db *gorm.DB, pageOffset, pageSize int) (vendors []Template, err error) {
if pageOffset >= 0 && pageSize > 0 {
db = db.Offset(pageOffset).Limit(pageSize)
}
if v.Name != "" {
db = db.Where("name = ?", v.Name)
}
if v.Uuid != 0 {
db = db.Where("uuid = ?", v.Uuid)
}
if err = db.Find(&vendors).Error; err != nil {
return nil, err
}
return
}
func (v Template) Get(db *gorm.DB) (vendor Template, err error) {
if notFound := db.Where("id = ?", v.ID).First(&vendor).RecordNotFound(); notFound {
return v, gorm.ErrRecordNotFound
}
return vendor, nil
}
func (v *Template) Create(db *gorm.DB) error {
return db.Create(v).Error
}
func (v *Template) Update(db *gorm.DB) error {
err := db.Save(v).Error
return err
}
func (v *Template) Delete(db *gorm.DB) error {
return db.Where("id = ?", v.ID).Delete(v).Error
}

View File

@ -0,0 +1,56 @@
/*
* @Date: 2021-03-21 19:54:57
* @LastEditors: viletyy
* @LastEditTime: 2021-07-09 14:44:37
* @FilePath: /potato/internal/routers/router.go
*/
package routers
import (
"time"
"github.com/gin-gonic/gin"
_ "github.com/swaggo/gin-swagger"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
_ "github.com/swaggo/gin-swagger/swaggerFiles"
_ "gitlink.org.cn/Gitlink/account-server/docs"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/internal/controller/api"
"gitlink.org.cn/Gitlink/account-server/internal/middleware"
)
var (
Engine = gin.Default()
)
func InitRouter() *gin.Engine {
gin.SetMode(global.GO_CONFIG.App.RunMode) // 设置运行模式
Engine.Use(middleware.AppInfo()) // 设置app信息
Engine.Use(middleware.ContextTimeout(time.Duration(global.GO_CONFIG.App.DefaultContextTimeout))) // 设置统一超时控制
Engine.Use(middleware.Translations()) // 设置自定义验证
Engine.Use(middleware.CORS()) // 设置跨域
if global.GO_CONFIG.App.RunMode == "debug" {
Engine.Use(gin.Logger()) // 设置log
Engine.Use(gin.Recovery()) // 设置recovery
} else {
Engine.Use(middleware.AccessLog())
}
Engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
apiRouterGroup := Engine.Group("../api")
// apiRouterGroup.Use(middleware.JWT())
templates := apiRouterGroup.Group("/templates")
template := api.NewTemplate()
{
templates.GET("", template.List)
templates.POST("", template.Create)
templates.GET("/:id", template.Get)
templates.PATCH("/:id", template.Update)
templates.DELETE("/:id", template.Delete)
}
return Engine
}

View File

@ -0,0 +1,27 @@
/*
* @Date: 2021-06-10 18:51:48
* @LastEditors: viletyy
* @LastEditTime: 2021-06-16 23:58:59
* @FilePath: /potato/internal/service/service.go
*/
package service
import (
"context"
otgorm "github.com/eddycjy/opentracing-gorm"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/internal/dao"
)
type Service struct {
Ctx context.Context
Dao *dao.Dao
}
func New(ctx context.Context) Service {
svc := Service{Ctx: ctx}
svc.Dao = dao.New(otgorm.WithContext(svc.Ctx, global.GO_DB))
return svc
}

View File

@ -0,0 +1,59 @@
package service
import (
"gitlink.org.cn/Gitlink/account-server/internal/model"
"gitlink.org.cn/Gitlink/account-server/pkg/app"
)
type CountTemplateRequest struct {
Name string `form:"name" json:"name" validate:"max=100"`
Uuid int `form:"uuid" json:"uuid"`
}
type TemplateListRequest struct {
Name string `form:"name" json:"name" validate:"max=100"`
Uuid int `form:"uuid" json:"uuid"`
}
type TemplateRequest struct {
ID int64 `form:"id" json:"id" validate:"required,gte=1"`
}
type CreateTemplateRequest struct {
Name string `form:"name" json:"name" validate:"required"`
Uuid int `form:"uuid" json:"uuid"`
}
type UpdateTemplateRequest struct {
ID int64 `form:"id" json:"id" validate:"required,gte=1"`
Name string `form:"name" json:"name"`
Uuid int `form:"uuid" json:"uuid"`
}
type DeleteTemplateRequest struct {
ID int64 `json:"id" validate:"required,gte=1"`
}
func (svc *Service) CountTemplate(param *CountTemplateRequest) (int, error) {
return svc.Dao.CountTemplate(param.Name, param.Uuid)
}
func (svc *Service) GetTemplateList(param *TemplateListRequest, paper *app.Pager) ([]model.Template, error) {
return svc.Dao.GetTemplateList(param.Name, param.Uuid, paper.Page, paper.PageSize)
}
func (svc *Service) GetTemplate(param *TemplateRequest) (model.Template, error) {
return svc.Dao.GetTemplate(param.ID)
}
func (svc *Service) CreateTemplate(param *CreateTemplateRequest) (model.Template, error) {
return svc.Dao.CreateTemplate(param.Name, param.Uuid)
}
func (svc *Service) UpdateTemplate(param *UpdateTemplateRequest) (model.Template, error) {
return svc.Dao.UpdateTemplate(param.ID, param.Name, param.Uuid)
}
func (svc *Service) DeleteTemplate(param *DeleteTemplateRequest) (model.Template, error) {
return svc.Dao.DeleteTemplate(param.ID)
}

52
main.go Normal file
View File

@ -0,0 +1,52 @@
package main
import (
"flag"
"github.com/viletyy/yolk/convert"
"gitlink.org.cn/Gitlink/account-server/global"
"gitlink.org.cn/Gitlink/account-server/initialize"
)
// @title AccountServer Api
// @version 1.0
// @description 账号服务
// @BasePath /api
var grpcPort string
var httpPort string
func main() {
global.GO_VP = initialize.Viper()
global.GO_LOG = initialize.Zap()
global.GO_DB = initialize.Gorm()
global.GO_REDIS = initialize.Redis()
go initialize.Cron()
go initialize.Migrate()
defer global.GO_DB.Close()
defer global.GO_REDIS.Close()
flag.StringVar(&grpcPort, "grpc_port", convert.ToString(global.GO_CONFIG.Server.GrpcPort), "启动grpc服务端口号")
flag.StringVar(&httpPort, "http_port", convert.ToString(global.GO_CONFIG.Server.HttpPort), "启动http服务端口号")
flag.Parse()
errs := make(chan error)
go func() {
err := initialize.RunHttpServer(httpPort)
if err != nil {
errs <- err
}
}()
go func() {
err := initialize.RunGrpcServer(grpcPort)
if err != nil {
errs <- err
}
}()
select {
case err := <-errs:
global.GO_LOG.Sugar().Fatalf("Run Server err: %v", err)
}
}

View File

@ -0,0 +1 @@
DROP table IF EXISTS templates;

View File

@ -0,0 +1,10 @@
CREATE TABLE `templates` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`uuid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_templates_deleted_at` (`deleted_at`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

60
pkg/app/app.go Normal file
View File

@ -0,0 +1,60 @@
/*
* @Date: 2021-06-10 16:47:58
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 23:53:10
* @FilePath: /potato/pkg/app/app.go
*/
package app
import (
"github.com/gin-gonic/gin"
"gitlink.org.cn/Gitlink/account-server/pkg/errcode"
)
type Response struct {
Ctx *gin.Context
}
type Pager struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int `json:"total"`
}
func NewResponse(ctx *gin.Context) *Response {
return &Response{Ctx: ctx}
}
func (r *Response) ToResponse(data interface{}) {
err := errcode.Success
err.WithData(data)
r.ToErrorResponse(err)
}
func (r *Response) ToResponseErrors(data interface{}) {
err := errcode.InvalidMultiParams
err.WithData(data)
r.ToErrorResponse(err)
}
func (r *Response) ToResponseList(list interface{}, total int) {
err := errcode.Success
err.WithData(map[string]interface{}{
"list": list,
"pager": Pager{
Page: GetPage(r.Ctx),
PageSize: GetPageSize(r.Ctx),
Total: total,
},
})
r.ToErrorResponse(err)
}
func (r *Response) ToErrorResponse(err *errcode.Error) {
response := gin.H{"code": err.Code, "msg": err.Msg}
data := err.Data
response["data"] = data
r.Ctx.JSON(err.StatusCode(), response)
}

60
pkg/app/form.go Normal file
View File

@ -0,0 +1,60 @@
/*
* @Date: 2021-06-10 18:10:14
* @LastEditors: viletyy
* @LastEditTime: 2021-06-11 01:15:10
* @FilePath: /potato/pkg/app/form.go
*/
package app
import (
"strings"
"github.com/gin-gonic/gin"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
type ValidError struct {
Key string
Message string
}
type ValidErrors []*ValidError
func (v *ValidError) Error() string {
return v.Message
}
func (v ValidErrors) Error() string {
return strings.Join(v.Errors(), ",")
}
func (v ValidErrors) Errors() (errs []string) {
for _, err := range v {
errs = append(errs, err.Error())
}
return
}
func BindAndValid(c *gin.Context, v interface{}) (bool, ValidErrors) {
var errs ValidErrors
err := c.ShouldBind(v)
if err != nil {
v := c.Value("trans")
trans, _ := v.(ut.Translator)
verrs, ok := err.(validator.ValidationErrors)
if !ok {
return false, errs
}
for key, value := range verrs.Translate(trans) {
errs = append(errs, &ValidError{
Key: key,
Message: value,
})
}
return false, errs
}
return true, nil
}

61
pkg/app/jwt.go Normal file
View File

@ -0,0 +1,61 @@
/*
* @Date: 2021-06-10 18:25:19
* @LastEditors: viletyy
* @LastEditTime: 2021-06-13 22:00:15
* @FilePath: /potato/pkg/app/jwt.go
*/
package app
import (
"time"
"github.com/golang-jwt/jwt"
"github.com/viletyy/yolk/crypt"
"gitlink.org.cn/Gitlink/account-server/global"
)
type Claims struct {
AppKey string `json:"app_key"`
AppSecret string `json:"app_secret"`
jwt.StandardClaims
}
func GetJWTSecret() []byte {
return []byte("account-server")
}
func GenerateToken(appKey, appSecret string) (string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(time.Duration(12*60*60) * time.Second)
claims := Claims{
AppKey: crypt.Md5Encode(appKey),
AppSecret: crypt.Md5Encode(appSecret),
StandardClaims: jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: global.GO_CONFIG.App.Name,
},
}
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tokenClaims.SignedString(GetJWTSecret())
return token, err
}
func ParseToken(token string) (*Claims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return GetJWTSecret(), nil
})
if err != nil {
return nil, err
}
if tokenClaims != nil {
if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
return claims, nil
}
}
return nil, err
}

46
pkg/app/paginator.go Normal file
View File

@ -0,0 +1,46 @@
/*
* @Date: 2021-06-10 15:27:36
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 16:58:28
* @FilePath: /potato/pkg/app/paginator.go
*/
package app
import (
"github.com/gin-gonic/gin"
"github.com/viletyy/yolk/convert"
"gitlink.org.cn/Gitlink/account-server/global"
)
func GetPageInfo(c *gin.Context) (page, pageSize int) {
page, _ = convert.StrTo(c.DefaultQuery("page", "1")).Int()
pageSize, _ = convert.StrTo(c.DefaultQuery("page_size", "10")).Int()
return
}
func GetPage(c *gin.Context) int {
page, _ := convert.StrTo(c.Query("page")).Int()
if page <= 0 {
return 1
}
return page
}
func GetPageSize(c *gin.Context) int {
pageSize, _ := convert.StrTo(c.Query("page_size")).Int()
if pageSize <= 0 {
return int(global.GO_CONFIG.App.PageSize)
}
return pageSize
}
func GetPageOffset(page, pageSize int) int {
result := 0
if page > 0 {
result = (page - 1) * pageSize
}
return result
}

View File

@ -0,0 +1,20 @@
/*
* @Date: 2021-06-10 16:25:21
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 23:52:39
* @FilePath: /potato/pkg/errcode/common_code.go
*/
package errcode
var (
Success = NewError(0, "请求成功")
ServerError = NewError(10000, "服务内部错误")
InvalidParams = NewError(10001, "参数错误")
InvalidMultiParams = NewError(10002, "多个参数错误")
NotFound = NewError(10003, "找不到数据")
UnauthorizedAuthNotExist = NewError(10004, "鉴权失败,找不到对应等 AppKey和 AppSecret")
UnauthorizedTokenError = NewError(10005, "鉴权失败Token 错误")
UnauthorizedTokenTimeout = NewError(10006, "鉴权失败Token 超时")
UnauthorizedTokenGenerate = NewError(10007, "鉴权失败Token 生成失败")
TooManyRequests = NewError(10008, "请求过多")
)

63
pkg/errcode/errcode.go Normal file
View File

@ -0,0 +1,63 @@
/*
* @Date: 2021-06-10 16:30:10
* @LastEditors: viletyy
* @LastEditTime: 2021-06-18 22:22:55
* @FilePath: /potato/pkg/errcode/errcode.go
*/
package errcode
import (
"fmt"
"net/http"
)
type Error struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
var codes = map[int]string{}
func NewError(code int, msg string) *Error {
if _, ok := codes[code]; ok {
panic(fmt.Sprintf("错误码 %d 已存在,请更换一个", code))
}
codes[code] = msg
return &Error{Code: code, Msg: msg}
}
func (e *Error) Error() string {
return fmt.Sprintf("错误码:%d错误信息%s", e.Code, e.Msg)
}
func (e *Error) Msgf(args []interface{}) string {
return fmt.Sprintf(e.Msg, args...)
}
func (e *Error) WithData(data interface{}) {
e.Data = data
}
func (e *Error) StatusCode() int {
switch e.Code {
case Success.Code:
return http.StatusOK
case ServerError.Code:
return http.StatusInternalServerError
case InvalidParams.Code:
return http.StatusBadRequest
case UnauthorizedAuthNotExist.Code:
fallthrough
case UnauthorizedTokenError.Code:
fallthrough
case UnauthorizedTokenGenerate.Code:
fallthrough
case UnauthorizedTokenTimeout.Code:
return http.StatusUnauthorized
case TooManyRequests.Code:
return http.StatusTooManyRequests
}
return http.StatusBadRequest
}

View File

@ -0,0 +1,16 @@
/*
* @Date: 2021-06-10 23:09:09
* @LastEditors: viletyy
* @LastEditTime: 2021-07-09 14:32:17
* @FilePath: /potato/pkg/errcode/module_code.go
*/
package errcode
var (
ErrorGetListFail = NewError(20101, "获取列表失败")
ErrorGetFail = NewError(20102, "获取数据失败")
ErrorCreateFail = NewError(20103, "创建数据失败")
ErrorUpdateFail = NewError(20104, "更新数据失败")
ErrorDeleteFail = NewError(20105, "删除数据失败")
ErrorCountFail = NewError(20106, "统计数据失败")
)

View File

@ -0,0 +1,20 @@
/*
* @Date: 2021-06-18 21:37:14
* @LastEditors: viletyy
* @LastEditTime: 2021-06-18 22:21:54
* @FilePath: /potato/pkg/errcode/rpc/rpc_common_code.go
*/
package rpc
var (
RpcSuccess = NewRpcError(0, "成功")
RpcFail = NewRpcError(10000, "内部错误")
RpcInvalidParams = NewRpcError(10001, "无效参数")
RpcUnauthorized = NewRpcError(10002, "认证错误")
RpcNotFound = NewRpcError(10003, "没有找到")
RpcUnknown = NewRpcError(10004, "未知")
RpcDeadlineExceeded = NewRpcError(10005, "超出最后截止期限")
RpcAccessDenied = NewRpcError(10006, "访问被拒绝")
RpcLimitExceed = NewRpcError(10007, "访问限制")
RpcMethodNotAllowed = NewRpcError(10008, "不支持该方法")
)

View File

@ -0,0 +1,81 @@
/*
* @Date: 2021-06-18 21:42:53
* @LastEditors: viletyy
* @LastEditTime: 2021-06-18 22:31:20
* @FilePath: /potato/pkg/errcode/rpc/rpc_errcode.go
*/
package rpc
import (
"fmt"
pb "gitlink.org.cn/Gitlink/account-server/proto"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
type RpcError struct {
Code int
Msg string
}
type Status struct {
*status.Status
}
var rpcCodes = map[int]string{}
func FromError(err error) *Status {
s, _ := status.FromError(err)
return &Status{s}
}
func NewRpcError(code int, msg string) *RpcError {
if _, ok := rpcCodes[code]; ok {
panic(fmt.Sprintf("错误码 %d 已经存在,请更换一个", code))
}
rpcCodes[code] = msg
return &RpcError{Code: code, Msg: msg}
}
func (e *RpcError) Error() string {
return fmt.Sprintf("错误码:%d错误信息%s", e.Code, e.Msg)
}
func ToRpcError(err *RpcError) error {
pbErr := &pb.Error{Code: int32(err.Code), Message: err.Msg}
s, _ := status.New(ToRpcCode(err.Code), err.Msg).WithDetails(pbErr)
return s.Err()
}
func ToRpcStatus(code int, msg string) *Status {
pbErr := &pb.Error{Code: int32(code), Message: msg}
s, _ := status.New(ToRpcCode(code), msg).WithDetails(pbErr)
return &Status{s}
}
func ToRpcCode(code int) codes.Code {
var statusCode codes.Code
switch code {
case RpcFail.Code:
statusCode = codes.Internal
case RpcInvalidParams.Code:
statusCode = codes.InvalidArgument
case RpcUnauthorized.Code:
statusCode = codes.Unauthenticated
case RpcAccessDenied.Code:
statusCode = codes.PermissionDenied
case RpcDeadlineExceeded.Code:
statusCode = codes.DeadlineExceeded
case RpcNotFound.Code:
statusCode = codes.NotFound
case RpcLimitExceed.Code:
statusCode = codes.ResourceExhausted
case RpcMethodNotAllowed.Code:
statusCode = codes.Unimplemented
default:
statusCode = codes.Unknown
}
return statusCode
}

View File

@ -0,0 +1,16 @@
/*
* @Date: 2021-06-18 22:32:02
* @LastEditors: viletyy
* @LastEditTime: 2021-06-18 22:33:40
* @FilePath: /potato/pkg/errcode/rpc/rpc_module_error.go
*/
package rpc
var (
RpcErrorGetTemplateListFail = NewRpcError(20101, "获取列表失败")
RpcErrorGetTemplateFail = NewRpcError(20102, "获取失败")
RpcErrorCreateTemplateFail = NewRpcError(20103, "创建失败")
RpcErrorUpdateTemplateFail = NewRpcError(20104, "更新失败")
RpcErrorDeleteTemplateFail = NewRpcError(20105, "删除失败")
RpcErrorCountTemplateFail = NewRpcError(20106, "统计失败")
)

37
pkg/rotatelogs_unix.go Normal file
View File

@ -0,0 +1,37 @@
/*
* @Date: 2021-03-22 16:44:06
* @LastEditors: viletyy
* @LastEditTime: 2021-06-10 15:18:37
* @FilePath: /potato/pkg/rotatelogs_unix.go
*/
// +build !windows
package pkg
import (
"os"
"path"
"time"
zaprotatelogs "github.com/lestrrat-go/file-rotatelogs"
"gitlink.org.cn/Gitlink/account-server/global"
"go.uber.org/zap/zapcore"
)
//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: GetWriteSyncer
//@description: zap logger中加入file-rotatelogs
//@return: zapcore.WriteSyncer, error
func GetWriteSyncer() (zapcore.WriteSyncer, error) {
fileWriter, err := zaprotatelogs.New(
path.Join(global.GO_CONFIG.Zap.Director, "%Y-%m-%d.log"),
zaprotatelogs.WithLinkName(global.GO_CONFIG.Zap.LinkName),
zaprotatelogs.WithMaxAge(7*24*time.Hour),
zaprotatelogs.WithRotationTime(24*time.Hour),
)
if global.GO_CONFIG.Zap.LogInConsole {
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileWriter)), err
}
return zapcore.AddSync(fileWriter), err
}

34
pkg/rotatelogs_windows.go Normal file
View File

@ -0,0 +1,34 @@
/*
* @Date: 2021-03-22 16:44:06
* @LastEditors: viletyy
* @LastEditTime: 2021-03-22 16:44:53
* @FilePath: /potato/utils/rotatelogs_windows.go
*/
package pkg
import (
"os"
"path"
"time"
zaprotatelogs "github.com/lestrrat-go/file-rotatelogs"
"gitlink.org.cn/Gitlink/account-server/global"
"go.uber.org/zap/zapcore"
)
//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: GetWriteSyncer
//@description: zap logger中加入file-rotatelogs
//@return: zapcore.WriteSyncer, error
func GetWriteSyncer() (zapcore.WriteSyncer, error) {
fileWriter, err := zaprotatelogs.New(
path.Join(global.GO_CONFIG.Zap.Director, "%Y-%m-%d.log"),
zaprotatelogs.WithMaxAge(7*24*time.Hour),
zaprotatelogs.WithRotationTime(24*time.Hour),
)
if global.GO_CONFIG.Zap.LogInConsole {
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileWriter)), err
}
return zapcore.AddSync(fileWriter), err
}

157
proto/common.pb.go Normal file
View File

@ -0,0 +1,157 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: proto/common.proto
package proto
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
anypb "google.golang.org/protobuf/types/known/anypb"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Pager struct {
Page int64 `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"`
PageSize int64 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
Total int64 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Pager) Reset() { *m = Pager{} }
func (m *Pager) String() string { return proto.CompactTextString(m) }
func (*Pager) ProtoMessage() {}
func (*Pager) Descriptor() ([]byte, []int) {
return fileDescriptor_1747d3070a2311a0, []int{0}
}
func (m *Pager) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Pager.Unmarshal(m, b)
}
func (m *Pager) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Pager.Marshal(b, m, deterministic)
}
func (m *Pager) XXX_Merge(src proto.Message) {
xxx_messageInfo_Pager.Merge(m, src)
}
func (m *Pager) XXX_Size() int {
return xxx_messageInfo_Pager.Size(m)
}
func (m *Pager) XXX_DiscardUnknown() {
xxx_messageInfo_Pager.DiscardUnknown(m)
}
var xxx_messageInfo_Pager proto.InternalMessageInfo
func (m *Pager) GetPage() int64 {
if m != nil {
return m.Page
}
return 0
}
func (m *Pager) GetPageSize() int64 {
if m != nil {
return m.PageSize
}
return 0
}
func (m *Pager) GetTotal() int64 {
if m != nil {
return m.Total
}
return 0
}
type Error struct {
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
Data *anypb.Any `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Error) Reset() { *m = Error{} }
func (m *Error) String() string { return proto.CompactTextString(m) }
func (*Error) ProtoMessage() {}
func (*Error) Descriptor() ([]byte, []int) {
return fileDescriptor_1747d3070a2311a0, []int{1}
}
func (m *Error) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Error.Unmarshal(m, b)
}
func (m *Error) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Error.Marshal(b, m, deterministic)
}
func (m *Error) XXX_Merge(src proto.Message) {
xxx_messageInfo_Error.Merge(m, src)
}
func (m *Error) XXX_Size() int {
return xxx_messageInfo_Error.Size(m)
}
func (m *Error) XXX_DiscardUnknown() {
xxx_messageInfo_Error.DiscardUnknown(m)
}
var xxx_messageInfo_Error proto.InternalMessageInfo
func (m *Error) GetCode() int32 {
if m != nil {
return m.Code
}
return 0
}
func (m *Error) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func (m *Error) GetData() *anypb.Any {
if m != nil {
return m.Data
}
return nil
}
func init() {
proto.RegisterType((*Pager)(nil), "Pager")
proto.RegisterType((*Error)(nil), "Error")
}
func init() { proto.RegisterFile("proto/common.proto", fileDescriptor_1747d3070a2311a0) }
var fileDescriptor_1747d3070a2311a0 = []byte{
// 222 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x8f, 0xc1, 0x4a, 0x03, 0x31,
0x10, 0x86, 0xa9, 0xed, 0xaa, 0x1d, 0x6f, 0xa1, 0x87, 0x55, 0x2f, 0xd2, 0x53, 0x2f, 0x4d, 0xa4,
0x3e, 0x81, 0x82, 0x78, 0x13, 0x59, 0x6f, 0x5e, 0x4a, 0xdc, 0x8e, 0x21, 0xb8, 0xc9, 0x2c, 0x93,
0x28, 0xb4, 0x4f, 0x2f, 0x99, 0xb0, 0x9e, 0x66, 0xbe, 0xfc, 0xe1, 0xcb, 0x1f, 0x50, 0x23, 0x53,
0x26, 0xd3, 0x53, 0x08, 0x14, 0xb5, 0xc0, 0xcd, 0xb5, 0x23, 0x72, 0x03, 0x1a, 0xa1, 0xcf, 0x9f,
0x2f, 0x63, 0xe3, 0xb1, 0x46, 0xeb, 0x57, 0x68, 0xde, 0xac, 0x43, 0x56, 0x0a, 0x16, 0xa3, 0x75,
0xd8, 0xce, 0xee, 0x66, 0x9b, 0x79, 0x27, 0xbb, 0xba, 0x85, 0x65, 0x99, 0xfb, 0xe4, 0x4f, 0xd8,
0x9e, 0x49, 0x70, 0x59, 0x0e, 0xde, 0xfd, 0x09, 0xd5, 0x0a, 0x9a, 0x4c, 0xd9, 0x0e, 0xed, 0x5c,
0x82, 0x0a, 0xeb, 0x3d, 0x34, 0xcf, 0xcc, 0x24, 0xbe, 0x9e, 0x0e, 0xd5, 0xd7, 0x74, 0xb2, 0xab,
0x16, 0x2e, 0x02, 0xa6, 0x54, 0x9e, 0x29, 0xb6, 0x65, 0x37, 0xa1, 0xda, 0xc0, 0xe2, 0x60, 0xb3,
0x15, 0xd7, 0xd5, 0x6e, 0xa5, 0x6b, 0x61, 0x3d, 0x15, 0xd6, 0x8f, 0xf1, 0xd8, 0xc9, 0x8d, 0xa7,
0xdd, 0xc7, 0xbd, 0xf3, 0x79, 0xf0, 0xf1, 0x5b, 0x13, 0x3b, 0xdd, 0x47, 0xf3, 0x52, 0xd1, 0x04,
0xdf, 0x33, 0x6d, 0x13, 0xf2, 0x2f, 0xf2, 0x36, 0xf9, 0x30, 0xfe, 0xff, 0xf8, 0x5c, 0xc6, 0xc3,
0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x82, 0xa0, 0x45, 0x2c, 0x1c, 0x01, 0x00, 0x00,
}

17
proto/common.proto Normal file
View File

@ -0,0 +1,17 @@
syntax = "proto3";
import "google/protobuf/any.proto";
option go_package= "gitlink.org.cn/Gitlink/account-server/proto";
message Pager {
int64 page = 1;
int64 page_size = 2;
int64 total = 3;
}
message Error {
int32 code = 1;
string message = 2;
google.protobuf.Any data = 3;
}

216
proto/template.pb.go Normal file
View File

@ -0,0 +1,216 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: proto/template.proto
package proto
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type GetTemplateListRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Uuid int64 `protobuf:"varint,2,opt,name=uuid,proto3" json:"uuid,omitempty"`
Page int64 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"`
PageSize int64 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetTemplateListRequest) Reset() { *m = GetTemplateListRequest{} }
func (m *GetTemplateListRequest) String() string { return proto.CompactTextString(m) }
func (*GetTemplateListRequest) ProtoMessage() {}
func (*GetTemplateListRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_dc851a26de071022, []int{0}
}
func (m *GetTemplateListRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetTemplateListRequest.Unmarshal(m, b)
}
func (m *GetTemplateListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetTemplateListRequest.Marshal(b, m, deterministic)
}
func (m *GetTemplateListRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetTemplateListRequest.Merge(m, src)
}
func (m *GetTemplateListRequest) XXX_Size() int {
return xxx_messageInfo_GetTemplateListRequest.Size(m)
}
func (m *GetTemplateListRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetTemplateListRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetTemplateListRequest proto.InternalMessageInfo
func (m *GetTemplateListRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *GetTemplateListRequest) GetUuid() int64 {
if m != nil {
return m.Uuid
}
return 0
}
func (m *GetTemplateListRequest) GetPage() int64 {
if m != nil {
return m.Page
}
return 0
}
func (m *GetTemplateListRequest) GetPageSize() int64 {
if m != nil {
return m.PageSize
}
return 0
}
type Template struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Uuid int64 `protobuf:"varint,3,opt,name=uuid,proto3" json:"uuid,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Template) Reset() { *m = Template{} }
func (m *Template) String() string { return proto.CompactTextString(m) }
func (*Template) ProtoMessage() {}
func (*Template) Descriptor() ([]byte, []int) {
return fileDescriptor_dc851a26de071022, []int{1}
}
func (m *Template) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Template.Unmarshal(m, b)
}
func (m *Template) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Template.Marshal(b, m, deterministic)
}
func (m *Template) XXX_Merge(src proto.Message) {
xxx_messageInfo_Template.Merge(m, src)
}
func (m *Template) XXX_Size() int {
return xxx_messageInfo_Template.Size(m)
}
func (m *Template) XXX_DiscardUnknown() {
xxx_messageInfo_Template.DiscardUnknown(m)
}
var xxx_messageInfo_Template proto.InternalMessageInfo
func (m *Template) GetId() int64 {
if m != nil {
return m.Id
}
return 0
}
func (m *Template) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *Template) GetUuid() int64 {
if m != nil {
return m.Uuid
}
return 0
}
type GetTemplateListReply struct {
List []*Template `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"`
Pager *Pager `protobuf:"bytes,2,opt,name=pager,proto3" json:"pager,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetTemplateListReply) Reset() { *m = GetTemplateListReply{} }
func (m *GetTemplateListReply) String() string { return proto.CompactTextString(m) }
func (*GetTemplateListReply) ProtoMessage() {}
func (*GetTemplateListReply) Descriptor() ([]byte, []int) {
return fileDescriptor_dc851a26de071022, []int{2}
}
func (m *GetTemplateListReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetTemplateListReply.Unmarshal(m, b)
}
func (m *GetTemplateListReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetTemplateListReply.Marshal(b, m, deterministic)
}
func (m *GetTemplateListReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetTemplateListReply.Merge(m, src)
}
func (m *GetTemplateListReply) XXX_Size() int {
return xxx_messageInfo_GetTemplateListReply.Size(m)
}
func (m *GetTemplateListReply) XXX_DiscardUnknown() {
xxx_messageInfo_GetTemplateListReply.DiscardUnknown(m)
}
var xxx_messageInfo_GetTemplateListReply proto.InternalMessageInfo
func (m *GetTemplateListReply) GetList() []*Template {
if m != nil {
return m.List
}
return nil
}
func (m *GetTemplateListReply) GetPager() *Pager {
if m != nil {
return m.Pager
}
return nil
}
func init() {
proto.RegisterType((*GetTemplateListRequest)(nil), "GetTemplateListRequest")
proto.RegisterType((*Template)(nil), "Template")
proto.RegisterType((*GetTemplateListReply)(nil), "GetTemplateListReply")
}
func init() { proto.RegisterFile("proto/template.proto", fileDescriptor_dc851a26de071022) }
var fileDescriptor_dc851a26de071022 = []byte{
// 286 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xcf, 0x4b, 0xc3, 0x30,
0x14, 0xc7, 0xed, 0x0f, 0xc7, 0x9a, 0x81, 0x83, 0x30, 0xb5, 0x4c, 0x85, 0xd2, 0x53, 0x2f, 0x4b,
0xa5, 0xfe, 0x07, 0xf3, 0xb0, 0x8b, 0x07, 0x49, 0xc5, 0x83, 0x17, 0xa9, 0xdd, 0xa3, 0x04, 0x9b,
0xa6, 0x4b, 0xd2, 0x81, 0xfb, 0xeb, 0x25, 0x89, 0x45, 0xd0, 0x9e, 0xde, 0x7b, 0x9f, 0x3e, 0xde,
0xe7, 0x4b, 0x83, 0x56, 0xbd, 0x14, 0x5a, 0xe4, 0x1a, 0x78, 0xdf, 0x56, 0x1a, 0x88, 0x1d, 0xd7,
0xd8, 0xd1, 0x5a, 0x70, 0x2e, 0x3a, 0xc7, 0xd2, 0x03, 0xba, 0xda, 0x81, 0x7e, 0xf9, 0x59, 0x7c,
0x62, 0x4a, 0x53, 0x38, 0x0c, 0xa0, 0x34, 0xc6, 0x28, 0xec, 0x2a, 0x0e, 0xb1, 0x97, 0x78, 0x59,
0x44, 0x6d, 0x6f, 0xd8, 0x30, 0xb0, 0x7d, 0xec, 0x27, 0x5e, 0x16, 0x50, 0xdb, 0x1b, 0xd6, 0x57,
0x0d, 0xc4, 0x81, 0x63, 0xa6, 0xc7, 0x37, 0x28, 0x32, 0xf5, 0x5d, 0xb1, 0x13, 0xc4, 0xa1, 0xfd,
0x30, 0x37, 0xa0, 0x64, 0x27, 0x48, 0xb7, 0x68, 0x3e, 0xfa, 0xf0, 0x05, 0xf2, 0xd9, 0xde, 0x2a,
0x02, 0xea, 0xbb, 0x63, 0x56, 0xea, 0x4f, 0x48, 0x83, 0x5f, 0x69, 0x5a, 0xa2, 0xd5, 0xbf, 0xd8,
0x7d, 0xfb, 0x85, 0xef, 0x50, 0xd8, 0x32, 0xa5, 0x63, 0x2f, 0x09, 0xb2, 0x45, 0x11, 0x91, 0x71,
0x83, 0x5a, 0x8c, 0x6f, 0xd1, 0xb9, 0x89, 0x21, 0xed, 0xfd, 0x45, 0x31, 0x23, 0xcf, 0x66, 0xa2,
0x0e, 0x16, 0xaf, 0x68, 0x39, 0xee, 0x97, 0x20, 0x8f, 0xac, 0x06, 0xfc, 0x88, 0x96, 0x7f, 0x3c,
0xf8, 0x9a, 0x4c, 0xff, 0xb0, 0xf5, 0x25, 0x99, 0x8a, 0x94, 0x9e, 0x6d, 0x8b, 0xb7, 0xfb, 0x86,
0xe9, 0x96, 0x75, 0x9f, 0x44, 0xc8, 0x86, 0xd4, 0x5d, 0xbe, 0x73, 0x63, 0xce, 0x59, 0x2d, 0xc5,
0x46, 0x81, 0x3c, 0x82, 0xdc, 0x28, 0xc6, 0xfb, 0x16, 0x72, 0xfb, 0x2e, 0x1f, 0x33, 0x5b, 0x1e,
0xbe, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa4, 0xb3, 0x98, 0xcb, 0xca, 0x01, 0x00, 0x00,
}

27
proto/template.proto Normal file
View File

@ -0,0 +1,27 @@
syntax = "proto3";
option go_package= "gitlink.org.cn/Gitlink/account-server/proto";
import "proto/common.proto";
service TemplateService {
rpc GetTemplateList(GetTemplateListRequest) returns (GetTemplateListReply) {}
}
message GetTemplateListRequest {
string name = 1;
int64 uuid = 2;
int64 page = 3;
int64 page_size = 4;
}
message Template {
int64 id = 1;
string name = 2;
int64 uuid = 3;
}
message GetTemplateListReply {
repeated Template list = 1;
Pager pager = 2;
}

101
proto/template_grpc.pb.go Normal file
View File

@ -0,0 +1,101 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package proto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// TemplateServiceClient is the client API for TemplateService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type TemplateServiceClient interface {
GetTemplateList(ctx context.Context, in *GetTemplateListRequest, opts ...grpc.CallOption) (*GetTemplateListReply, error)
}
type templateServiceClient struct {
cc grpc.ClientConnInterface
}
func NewTemplateServiceClient(cc grpc.ClientConnInterface) TemplateServiceClient {
return &templateServiceClient{cc}
}
func (c *templateServiceClient) GetTemplateList(ctx context.Context, in *GetTemplateListRequest, opts ...grpc.CallOption) (*GetTemplateListReply, error) {
out := new(GetTemplateListReply)
err := c.cc.Invoke(ctx, "/TemplateService/GetTemplateList", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// TemplateServiceServer is the server API for TemplateService service.
// All implementations must embed UnimplementedTemplateServiceServer
// for forward compatibility
type TemplateServiceServer interface {
GetTemplateList(context.Context, *GetTemplateListRequest) (*GetTemplateListReply, error)
mustEmbedUnimplementedTemplateServiceServer()
}
// UnimplementedTemplateServiceServer must be embedded to have forward compatible implementations.
type UnimplementedTemplateServiceServer struct {
}
func (UnimplementedTemplateServiceServer) GetTemplateList(context.Context, *GetTemplateListRequest) (*GetTemplateListReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTemplateList not implemented")
}
func (UnimplementedTemplateServiceServer) mustEmbedUnimplementedTemplateServiceServer() {}
// UnsafeTemplateServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to TemplateServiceServer will
// result in compilation errors.
type UnsafeTemplateServiceServer interface {
mustEmbedUnimplementedTemplateServiceServer()
}
func RegisterTemplateServiceServer(s grpc.ServiceRegistrar, srv TemplateServiceServer) {
s.RegisterService(&TemplateService_ServiceDesc, srv)
}
func _TemplateService_GetTemplateList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetTemplateListRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TemplateServiceServer).GetTemplateList(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/TemplateService/GetTemplateList",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TemplateServiceServer).GetTemplateList(ctx, req.(*GetTemplateListRequest))
}
return interceptor(ctx, in, info, handler)
}
// TemplateService_ServiceDesc is the grpc.ServiceDesc for TemplateService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var TemplateService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "TemplateService",
HandlerType: (*TemplateServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetTemplateList",
Handler: _TemplateService_GetTemplateList_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/template.proto",
}

3
scripts/gen_proto.sh Normal file
View File

@ -0,0 +1,3 @@
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
./proto/*.proto

50
server/user.go Normal file
View File

@ -0,0 +1,50 @@
package server
import (
"context"
"encoding/json"
"gitlink.org.cn/Gitlink/account-server/internal/service"
"gitlink.org.cn/Gitlink/account-server/pkg/app"
"gitlink.org.cn/Gitlink/account-server/pkg/errcode/rpc"
pb "gitlink.org.cn/Gitlink/account-server/proto"
)
type TemplateServer struct {
pb.UnimplementedTemplateServiceServer
}
func NewTemplateServer() *TemplateServer {
return &TemplateServer{}
}
func (t *TemplateServer) GetTemplateList(ctx context.Context, r *pb.GetTemplateListRequest) (*pb.GetTemplateListReply, error) {
svc := service.New(ctx)
dbTemplateList, err := svc.Dao.GetTemplateList(r.GetName(), int(r.GetUuid()), int(r.GetPage()), int(r.GetPageSize()))
if err != nil {
return nil, rpc.ToRpcError(rpc.RpcErrorGetTemplateListFail)
}
total, err := svc.Dao.CountTemplate(r.GetName(), int(r.GetUuid()))
if err != nil {
return nil, rpc.ToRpcError(rpc.RpcErrorCountTemplateFail)
}
data := map[string]interface{}{
"list": dbTemplateList,
"pager": app.Pager{
Page: int(r.GetPage()),
PageSize: int(r.GetPageSize()),
Total: total,
},
}
byteData, err := json.Marshal(data)
if err != nil {
return nil, rpc.ToRpcError(rpc.RpcInvalidParams)
}
userList := pb.GetTemplateListReply{}
err = json.Unmarshal(byteData, &userList)
if err != nil {
return nil, rpc.ToRpcError(rpc.RpcInvalidParams)
}
return &userList, nil
}