mirror of
https://git.freecumextremist.com/grumbulon/pomme.git
synced 2024-12-22 17:20:44 +00:00
swagger updates, moved structs and types into types.go, and made helpers.go for custom handlers
This commit is contained in:
parent
9d87ae4728
commit
295360fd05
9 changed files with 137 additions and 127 deletions
33
docs/docs.go
33
docs/docs.go
|
@ -50,13 +50,13 @@ const docTemplate = `{
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "authFailed is a 401 error when logging in fails, includes realm",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,13 +100,13 @@ const docTemplate = `{
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "internalServerError is a 500 server error with a logged error call back",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,13 +150,13 @@ const docTemplate = `{
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "internalServerError is a 500 server error with a logged error call back",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,15 @@ const docTemplate = `{
|
|||
}
|
||||
},
|
||||
"definitions": {
|
||||
"internal.GenericResponse-internal_Response": {
|
||||
"internal.Response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.SwaggerGenericResponse-internal_Response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"response": {
|
||||
|
@ -176,17 +184,6 @@ const docTemplate = `{
|
|||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.Response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
|
|
@ -41,13 +41,13 @@
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "authFailed is a 401 error when logging in fails, includes realm",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,13 +91,13 @@
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "internalServerError is a 500 server error with a logged error call back",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,13 +141,13 @@
|
|||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "internalServerError is a 500 server error with a logged error call back",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal.GenericResponse-internal_Response"
|
||||
"$ref": "#/definitions/internal.SwaggerGenericResponse-internal_Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,15 @@
|
|||
}
|
||||
},
|
||||
"definitions": {
|
||||
"internal.GenericResponse-internal_Response": {
|
||||
"internal.Response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.SwaggerGenericResponse-internal_Response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"response": {
|
||||
|
@ -167,17 +175,6 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.Response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
definitions:
|
||||
internal.GenericResponse-internal_Response:
|
||||
internal.Response:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
internal.SwaggerGenericResponse-internal_Response:
|
||||
properties:
|
||||
response:
|
||||
allOf:
|
||||
- $ref: '#/definitions/internal.Response'
|
||||
description: Response items
|
||||
type: object
|
||||
internal.Response:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
info:
|
||||
contact: {}
|
||||
description: Pomme is a service that parses zonefiles
|
||||
|
@ -44,11 +42,11 @@ paths:
|
|||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/internal.GenericResponse-internal_Response'
|
||||
$ref: '#/definitions/internal.SwaggerGenericResponse-internal_Response'
|
||||
"401":
|
||||
description: authFailed is a 401 error when logging in fails, includes realm
|
||||
schema:
|
||||
$ref: '#/definitions/internal.GenericResponse-internal_Response'
|
||||
$ref: '#/definitions/internal.SwaggerGenericResponse-internal_Response'
|
||||
summary: authenticate as a regular user
|
||||
tags:
|
||||
- accounts
|
||||
|
@ -77,12 +75,12 @@ paths:
|
|||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/internal.GenericResponse-internal_Response'
|
||||
$ref: '#/definitions/internal.SwaggerGenericResponse-internal_Response'
|
||||
"500":
|
||||
description: internalServerError is a 500 server error with a logged error
|
||||
call back
|
||||
schema:
|
||||
$ref: '#/definitions/internal.GenericResponse-internal_Response'
|
||||
$ref: '#/definitions/internal.SwaggerGenericResponse-internal_Response'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: parse your zonefile
|
||||
|
@ -113,12 +111,12 @@ paths:
|
|||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/internal.GenericResponse-internal_Response'
|
||||
$ref: '#/definitions/internal.SwaggerGenericResponse-internal_Response'
|
||||
"500":
|
||||
description: internalServerError is a 500 server error with a logged error
|
||||
call back
|
||||
schema:
|
||||
$ref: '#/definitions/internal.GenericResponse-internal_Response'
|
||||
$ref: '#/definitions/internal.SwaggerGenericResponse-internal_Response'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: upload a zonefile
|
||||
|
|
|
@ -1,83 +1,16 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal"
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal/db"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/httplog"
|
||||
"github.com/go-chi/httprate"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/go-chi/render"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type key int
|
||||
|
||||
const (
|
||||
keyPrincipalContextID key = iota
|
||||
)
|
||||
|
||||
// setDBMiddleware is the http Handler func for the GORM middleware with context.
|
||||
func setDBMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var pommeDB *gorm.DB
|
||||
c, err := internal.ReadConfig()
|
||||
if err != nil {
|
||||
log.Printf("No config file defined: %v", err)
|
||||
}
|
||||
|
||||
switch r.Header.Get("User-Agent") {
|
||||
case "pomme-api-test-slave":
|
||||
pommeDB = db.InitDb(c.TestDB)
|
||||
default:
|
||||
pommeDB = db.InitDb(c.DB)
|
||||
}
|
||||
|
||||
timeoutContext, cancelContext := context.WithTimeout(context.Background(), time.Second)
|
||||
ctx := context.WithValue(r.Context(), keyPrincipalContextID, pommeDB.WithContext(timeoutContext))
|
||||
defer cancelContext()
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
type GenericResponse[T map[string]any] struct {
|
||||
Response map[string]any `json:"response,omitempty"`
|
||||
}
|
||||
|
||||
func APIError[T map[string]any](w http.ResponseWriter, r *http.Request, v map[string]any) {
|
||||
logger := httplog.NewLogger("Pomme", httplog.Options{
|
||||
JSON: true,
|
||||
})
|
||||
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
switch v["realm"] {
|
||||
case nil:
|
||||
w.Header().Add("API Error", v["message"].(string))
|
||||
default:
|
||||
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`realm="%s"`, v["realm"].(string)))
|
||||
w.Header().Add("API Error", v["message"].(string))
|
||||
}
|
||||
|
||||
w.WriteHeader(v["status"].(int))
|
||||
|
||||
render.JSON(w, r, v)
|
||||
|
||||
switch v["error"] {
|
||||
case nil:
|
||||
logger.Info().Msg(fmt.Sprint(v["message"]))
|
||||
default:
|
||||
logger.Error().Msg(fmt.Sprint(v["error"]))
|
||||
}
|
||||
}
|
||||
|
||||
// API subroute handler.
|
||||
func API() http.Handler {
|
||||
api := chi.NewRouter()
|
||||
|
|
|
@ -22,8 +22,8 @@ import (
|
|||
// @Produce json
|
||||
// @Param username query string true "Username"
|
||||
// @Param password query string true "Password"
|
||||
// @Success 200 {object} internal.GenericResponse[internal.Response]
|
||||
// @failure 401 {object} internal.GenericResponse[internal.Response] "authFailed is a 401 error when logging in fails, includes realm"
|
||||
// @Success 200 {object} internal.SwaggerGenericResponse[internal.Response]
|
||||
// @failure 401 {object} internal.SwaggerGenericResponse[internal.Response] "authFailed is a 401 error when logging in fails, includes realm"
|
||||
// @Router /api/login [post]
|
||||
func Login(w http.ResponseWriter, r *http.Request) {
|
||||
var result internal.User
|
||||
|
|
75
internal/api/helpers.go
Normal file
75
internal/api/helpers.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal"
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal/db"
|
||||
"github.com/go-chi/httplog"
|
||||
"github.com/go-chi/render"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// setDBMiddleware is the http Handler func for the GORM middleware with context.
|
||||
func setDBMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var pommeDB *gorm.DB
|
||||
c, err := internal.ReadConfig()
|
||||
if err != nil {
|
||||
log.Printf("No config file defined: %v", err)
|
||||
}
|
||||
|
||||
switch r.Header.Get("User-Agent") {
|
||||
case "pomme-api-test-slave":
|
||||
pommeDB = db.InitDb(c.TestDB)
|
||||
default:
|
||||
pommeDB = db.InitDb(c.DB)
|
||||
}
|
||||
|
||||
timeoutContext, cancelContext := context.WithTimeout(context.Background(), time.Second)
|
||||
ctx := context.WithValue(r.Context(), keyPrincipalContextID, pommeDB.WithContext(timeoutContext))
|
||||
defer cancelContext()
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
func APIError[T map[string]any](w http.ResponseWriter, r *http.Request, v map[string]any) {
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
logHandler(v)
|
||||
|
||||
switch v["realm"] {
|
||||
case nil:
|
||||
w.Header().Add("API Error", v["message"].(string))
|
||||
default:
|
||||
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`realm="%s"`, v["realm"].(string)))
|
||||
w.Header().Add("API Error", v["message"].(string))
|
||||
}
|
||||
|
||||
w.WriteHeader(v["status"].(int))
|
||||
|
||||
delete(v, "error")
|
||||
|
||||
render.JSON(w, r, v)
|
||||
}
|
||||
|
||||
func logHandler(v map[string]any) {
|
||||
logger := httplog.NewLogger("Pomme", httplog.Options{
|
||||
JSON: true,
|
||||
})
|
||||
|
||||
switch v["error"] {
|
||||
default:
|
||||
logger.Error().Msg(v["error"].(string))
|
||||
fallthrough
|
||||
case nil:
|
||||
logger.Info().Msg(v["message"].(string))
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,14 @@ package api
|
|||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
const (
|
||||
keyPrincipalContextID key = iota
|
||||
)
|
||||
|
||||
type genericResponseFields map[string]any
|
||||
|
||||
type key int
|
||||
|
||||
// ZoneRequest represents a Zone file request.
|
||||
type ZoneRequest struct {
|
||||
*Zone
|
||||
|
@ -17,4 +25,6 @@ type Zone struct {
|
|||
Body string `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
type genericResponseFields map[string]any
|
||||
type GenericResponse[T map[string]any] struct {
|
||||
Response map[string]any `json:"response,omitempty"`
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ import (
|
|||
// @Accept mpfd
|
||||
// @Produce json
|
||||
// @Param file formData file true "Zonefile to upload"
|
||||
// @Success 200 {object} internal.GenericResponse[internal.Response]
|
||||
// @Failure 500 {object} internal.GenericResponse[internal.Response] "internalServerError is a 500 server error with a logged error call back"
|
||||
// @Success 200 {object} internal.SwaggerGenericResponse[internal.Response]
|
||||
// @Failure 500 {object} internal.SwaggerGenericResponse[internal.Response] "internalServerError is a 500 server error with a logged error call back"
|
||||
// @Param Authorization header string true "Bearer Token"
|
||||
//
|
||||
// @Security Bearer
|
||||
|
@ -114,8 +114,8 @@ func ReceiveFile(w http.ResponseWriter, r *http.Request) {
|
|||
// @Accept mpfd
|
||||
// @Produce json
|
||||
// @Param filename query string true "Zonefile name"
|
||||
// @Success 200 {object} internal.GenericResponse[internal.Response]
|
||||
// @Failure 500 {object} internal.GenericResponse[internal.Response] "internalServerError is a 500 server error with a logged error call back"
|
||||
// @Success 200 {object} internal.SwaggerGenericResponse[internal.Response]
|
||||
// @Failure 500 {object} internal.SwaggerGenericResponse[internal.Response] "internalServerError is a 500 server error with a logged error call back"
|
||||
// @Param Authorization header string true "Bearer Token"
|
||||
//
|
||||
// @Security Bearer
|
||||
|
|
|
@ -37,9 +37,9 @@ type Config struct {
|
|||
TestDB string
|
||||
}
|
||||
|
||||
// GenericNestedResponse[T]
|
||||
// @Description Some Generic List Response.
|
||||
type GenericResponse[T any] struct {
|
||||
// SwaggerGenericResponse[T]
|
||||
// @Description Generic Response for Swagger.
|
||||
type SwaggerGenericResponse[T any] struct {
|
||||
// Response items
|
||||
Response T
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue