You've already forked golang-saas-starter-kit
mirror of
https://github.com/raseels-repos/golang-saas-starter-kit.git
synced 2025-06-15 00:15:15 +02:00
fixed internal package unittests
This commit is contained in:
@ -24,3 +24,53 @@ To build using the docker file, need to be in the project root directory. `Docke
|
||||
```bash
|
||||
docker build -f cmd/web-api/Dockerfile -t saas-web-api .
|
||||
```
|
||||
|
||||
|
||||
## API Documentation
|
||||
|
||||
Documentation is generated using [swag](https://github.com/swaggo/swag)
|
||||
|
||||
Download swag by using:
|
||||
```bash
|
||||
go get -u github.com/swaggo/swag/cmd/swag
|
||||
```
|
||||
|
||||
Run `swag init` in the service's root folder which contains the main.go file. This will parse your comments and generate the required files (docs folder and docs/docs.go).
|
||||
```bash
|
||||
swag init
|
||||
```
|
||||
|
||||
|
||||
### Trouble shooting
|
||||
|
||||
If you run into errors running `swag init` try the following:
|
||||
|
||||
|
||||
#### cannot find package
|
||||
Try to install the packages to your $GOPATH.
|
||||
|
||||
```bash
|
||||
GO111MODULE=off go get github.com/leodido/go-urn
|
||||
GO111MODULE=off go get github.com/lib/pq/oid
|
||||
GO111MODULE=off go get github.com/lib/pq/scram
|
||||
GO111MODULE=off go get github.com/tinylib/msgp/msgp
|
||||
GO111MODULE=off go get gopkg.in/DataDog/dd-trace-go.v1/ddtrace
|
||||
```
|
||||
|
||||
#### error writing go.mod
|
||||
|
||||
Need to update pkg directory permissions.
|
||||
|
||||
Full error:
|
||||
```bash
|
||||
error writing go.mod: open /Users/leebrown/go/pkg/mod/github.com/lib/pq@v1.1.1/go.mod691440060.tmp: permission denied
|
||||
|
||||
```
|
||||
|
||||
Ensure the `pkg` directory used for go module cache has the correct permissions.
|
||||
```bash
|
||||
sudo chown -R $(whoami):staff ${HOME}/go/pkg
|
||||
sudo chmod -R 755 ${HOME}/go/pkg
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag at
|
||||
// 2019-06-24 15:42:25.999684 -0800 AKDT m=+0.030714022
|
||||
// 2019-06-24 20:15:37.524606 -0800 AKDT m=+13.872100491
|
||||
|
||||
package docs
|
||||
|
||||
@ -16,10 +16,10 @@ var doc = `{
|
||||
"info": {
|
||||
"description": "This is a sample server celler server.",
|
||||
"title": "SaaS Example API",
|
||||
"termsOfService": "http://geeksinthewoods.com/terms",
|
||||
"termsOfService": "/terms",
|
||||
"contact": {
|
||||
"name": "API Support",
|
||||
"url": "https://gitlab.com/geeks-accelerator/oss/saas-starter-kit",
|
||||
"url": "/support",
|
||||
"email": "support@geeksinthewoods.com"
|
||||
},
|
||||
"license": {
|
||||
@ -30,20 +30,140 @@ var doc = `{
|
||||
},
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {},
|
||||
"paths": {
|
||||
"/accounts/{id}": {
|
||||
"get": {
|
||||
"description": "get string by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"summary": "Read returns the specified account from the system.",
|
||||
"operationId": "get-string-by-int",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Account ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/account.Account"
|
||||
},
|
||||
"headers": {
|
||||
"Token": {
|
||||
"type": "string",
|
||||
"description": "qwerty"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/web.Error"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/web.Error"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/web.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"account.Account": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address1": {
|
||||
"type": "string"
|
||||
},
|
||||
"address2": {
|
||||
"type": "string"
|
||||
},
|
||||
"archived_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"billing_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
},
|
||||
"country": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"signup_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "AccountStatus"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"zipcode": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"web.Error": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"err": {
|
||||
"type": "error"
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "FieldError"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"ApiKeyAuth": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
},
|
||||
"BasicAuth": {
|
||||
"type": "basic"
|
||||
},
|
||||
"OAuth2Password": {
|
||||
"type": "oauth2",
|
||||
"flow": "password",
|
||||
"tokenUrl": "https://example.com/v1/oauth/token"
|
||||
"tokenUrl": "/v1/oauth/token"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
@ -3,10 +3,10 @@
|
||||
"info": {
|
||||
"description": "This is a sample server celler server.",
|
||||
"title": "SaaS Example API",
|
||||
"termsOfService": "http://geeksinthewoods.com/terms",
|
||||
"termsOfService": "/terms",
|
||||
"contact": {
|
||||
"name": "API Support",
|
||||
"url": "https://gitlab.com/geeks-accelerator/oss/saas-starter-kit",
|
||||
"url": "/support",
|
||||
"email": "support@geeksinthewoods.com"
|
||||
},
|
||||
"license": {
|
||||
@ -17,20 +17,140 @@
|
||||
},
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {},
|
||||
"paths": {
|
||||
"/accounts/{id}": {
|
||||
"get": {
|
||||
"description": "get string by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"summary": "Read returns the specified account from the system.",
|
||||
"operationId": "get-string-by-int",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Account ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/account.Account"
|
||||
},
|
||||
"headers": {
|
||||
"Token": {
|
||||
"type": "string",
|
||||
"description": "qwerty"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/web.Error"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/web.Error"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/web.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"account.Account": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address1": {
|
||||
"type": "string"
|
||||
},
|
||||
"address2": {
|
||||
"type": "string"
|
||||
},
|
||||
"archived_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"billing_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"city": {
|
||||
"type": "string"
|
||||
},
|
||||
"country": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"region": {
|
||||
"type": "string"
|
||||
},
|
||||
"signup_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "AccountStatus"
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"zipcode": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"web.Error": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"err": {
|
||||
"type": "error"
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "FieldError"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"ApiKeyAuth": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
},
|
||||
"BasicAuth": {
|
||||
"type": "basic"
|
||||
},
|
||||
"OAuth2Password": {
|
||||
"type": "oauth2",
|
||||
"flow": "password",
|
||||
"tokenUrl": "https://example.com/v1/oauth/token"
|
||||
"tokenUrl": "/v1/oauth/token"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +1,106 @@
|
||||
basePath: '{{.BasePath}}'
|
||||
definitions:
|
||||
account.Account:
|
||||
properties:
|
||||
address1:
|
||||
type: string
|
||||
address2:
|
||||
type: string
|
||||
archived_at:
|
||||
type: string
|
||||
billing_user_id:
|
||||
type: string
|
||||
city:
|
||||
type: string
|
||||
country:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
region:
|
||||
type: string
|
||||
signup_user_id:
|
||||
type: string
|
||||
status:
|
||||
type: AccountStatus
|
||||
timezone:
|
||||
type: string
|
||||
updated_at:
|
||||
type: string
|
||||
zipcode:
|
||||
type: string
|
||||
type: object
|
||||
web.Error:
|
||||
properties:
|
||||
err:
|
||||
type: error
|
||||
fields:
|
||||
items:
|
||||
type: FieldError
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
host: '{{.Host}}'
|
||||
info:
|
||||
contact:
|
||||
email: support@geeksinthewoods.com
|
||||
name: API Support
|
||||
url: https://gitlab.com/geeks-accelerator/oss/saas-starter-kit
|
||||
url: /support
|
||||
description: This is a sample server celler server.
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
termsOfService: http://geeksinthewoods.com/terms
|
||||
termsOfService: /terms
|
||||
title: SaaS Example API
|
||||
version: '{{.Version}}'
|
||||
paths: {}
|
||||
paths:
|
||||
/accounts/{id}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: get string by ID
|
||||
operationId: get-string-by-int
|
||||
parameters:
|
||||
- description: Account ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
headers:
|
||||
Token:
|
||||
description: qwerty
|
||||
type: string
|
||||
schema:
|
||||
$ref: '#/definitions/account.Account'
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/web.Error'
|
||||
type: object
|
||||
"403":
|
||||
description: Forbidden
|
||||
schema:
|
||||
$ref: '#/definitions/web.Error'
|
||||
type: object
|
||||
"404":
|
||||
description: Not Found
|
||||
schema:
|
||||
$ref: '#/definitions/web.Error'
|
||||
type: object
|
||||
summary: Read returns the specified account from the system.
|
||||
securityDefinitions:
|
||||
ApiKeyAuth:
|
||||
in: header
|
||||
name: Authorization
|
||||
type: apiKey
|
||||
BasicAuth:
|
||||
type: basic
|
||||
OAuth2Password:
|
||||
flow: password
|
||||
tokenUrl: https://example.com/v1/oauth/token
|
||||
tokenUrl: /v1/oauth/token
|
||||
type: oauth2
|
||||
swagger: "2.0"
|
||||
|
@ -39,7 +39,19 @@ func (a *Account) Find(ctx context.Context, w http.ResponseWriter, r *http.Reque
|
||||
return web.RespondJson(ctx, w, res, http.StatusOK)
|
||||
}
|
||||
|
||||
// Read returns the specified account from the system.
|
||||
// Read godoc
|
||||
// @Summary Read returns the specified account from the system.
|
||||
// @Description get string by ID
|
||||
// @ID get-string-by-int
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Account ID"
|
||||
// @Success 200 {object} account.Account
|
||||
// @Header 200 {string} Token "qwerty"
|
||||
// @Failure 400 {object} web.Error
|
||||
// @Failure 403 {object} web.Error
|
||||
// @Failure 404 {object} web.Error
|
||||
// @Router /accounts/{id} [get]
|
||||
func (a *Account) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
|
||||
claims, ok := ctx.Value(auth.Key).(auth.Claims)
|
||||
if !ok {
|
||||
|
@ -40,7 +40,7 @@ func API(shutdown chan os.Signal, log *log.Logger, masterDB *sqlx.DB, redis *red
|
||||
app.Handle("PATCH", "/v1/users/switch-account/:accountId", u.SwitchAccount, mid.Authenticate(authenticator))
|
||||
|
||||
// This route is not authenticated
|
||||
app.Handle("GET", "/v1/oauth/token", u.Token)
|
||||
app.Handle("POST", "/v1/oauth/token", u.Token)
|
||||
|
||||
// Register account endpoints.
|
||||
a := Account{
|
||||
@ -65,8 +65,10 @@ func API(shutdown chan os.Signal, log *log.Logger, masterDB *sqlx.DB, redis *red
|
||||
app.Handle("DELETE", "/v1/projects/:id", p.Delete, mid.Authenticate(authenticator), mid.HasRole(auth.RoleAdmin))
|
||||
|
||||
// Register swagger documentation.
|
||||
app.Handle("GET", "/swagger/", saasSwagger.WrapHandler, mid.Authenticate(authenticator))
|
||||
app.Handle("GET", "/swagger/*", saasSwagger.WrapHandler, mid.Authenticate(authenticator))
|
||||
// TODO: Add authentication. Current authenticator requires an Authorization header
|
||||
// which breaks the browser experience.
|
||||
app.Handle("GET", "/swagger/", saasSwagger.WrapHandler)
|
||||
app.Handle("GET", "/swagger/*", saasSwagger.WrapHandler)
|
||||
|
||||
return app
|
||||
}
|
||||
|
@ -42,23 +42,17 @@ var service = "WEB_API"
|
||||
|
||||
// @title SaaS Example API
|
||||
// @description This is a sample server celler server.
|
||||
// @termsOfService http://geeksinthewoods.com/terms
|
||||
// @termsOfService http://example.com/terms
|
||||
|
||||
// @contact.name API Support
|
||||
// @contact.email support@geeksinthewoods.com
|
||||
// @contact.url https://gitlab.com/geeks-accelerator/oss/saas-starter-kit
|
||||
// @contact.url http://example.com/support
|
||||
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// @securityDefinitions.basic BasicAuth
|
||||
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
|
||||
// @securitydefinitions.oauth2.password OAuth2Password
|
||||
// @tokenUrl https://example.com/v1/oauth/token
|
||||
// @tokenUrl /v1/oauth/token
|
||||
|
||||
func main() {
|
||||
|
||||
@ -101,7 +95,7 @@ func main() {
|
||||
Database string `default:"shared" envconfig:"DATABASE"`
|
||||
Driver string `default:"postgres" envconfig:"DRIVER"`
|
||||
Timezone string `default:"utc" envconfig:"TIMEZONE"`
|
||||
DisableTLS bool `default:"false" envconfig:"DISABLE_TLS"`
|
||||
DisableTLS bool `default:"true" envconfig:"DISABLE_TLS"`
|
||||
}
|
||||
Trace struct {
|
||||
Host string `default:"127.0.0.1" envconfig:"DD_TRACE_AGENT_HOSTNAME"`
|
||||
|
4
example-project/cmd/web-api/sample.env
Normal file
4
example-project/cmd/web-api/sample.env
Normal file
@ -0,0 +1,4 @@
|
||||
export WEB_API_DB_HOST=127.0.0.1:5433
|
||||
export WEB_API_DB_USER=postgres
|
||||
export WEB_API_DB_PASS=postgres
|
||||
export WEB_API_DB_DISABLE_TLS=true
|
Reference in New Issue
Block a user