Compare commits
	
		
			11 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						3dee3e72af
	
				 | 
					
					
						|||
| 
						
						
							
						
						f5914e5c38
	
				 | 
					
					
						|||
| 
						
						
							
						
						5a5a7179e9
	
				 | 
					
					
						|||
| 
						
						
							
						
						6c57d63891
	
				 | 
					
					
						|||
| 
						
						
							
						
						b502e2fbd5
	
				 | 
					
					
						|||
| 
						
						
							
						
						c9475d0093
	
				 | 
					
					
						|||
| 
						
						
							
						
						1cc19e0085
	
				 | 
					
					
						|||
| 
						
						
							
						
						b792806481
	
				 | 
					
					
						|||
| 
						
						
							
						
						ea6a4a7080
	
				 | 
					
					
						|||
| 
						
						
							
						
						de6fe4991c
	
				 | 
					
					
						|||
| 
						
						
							
						
						1d068b2655
	
				 | 
					
					
						
							
								
								
									
										16
									
								
								docs/docs.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								docs/docs.go
									
									
									
									
									
								
							@@ -70,6 +70,15 @@ const docTemplate = `{
 | 
			
		||||
                        "description": "Barcode height",
 | 
			
		||||
                        "name": "height",
 | 
			
		||||
                        "in": "query"
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "maximum": 100,
 | 
			
		||||
                        "minimum": 0,
 | 
			
		||||
                        "type": "integer",
 | 
			
		||||
                        "default": 10,
 | 
			
		||||
                        "description": "Padding around the barcode (included in image size)",
 | 
			
		||||
                        "name": "padding",
 | 
			
		||||
                        "in": "query"
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                "responses": {}
 | 
			
		||||
@@ -312,18 +321,11 @@ const docTemplate = `{
 | 
			
		||||
        "models.Group": {
 | 
			
		||||
            "type": "object",
 | 
			
		||||
            "required": [
 | 
			
		||||
                "id",
 | 
			
		||||
                "name"
 | 
			
		||||
            ],
 | 
			
		||||
            "properties": {
 | 
			
		||||
                "id": {
 | 
			
		||||
                    "type": "integer"
 | 
			
		||||
                },
 | 
			
		||||
                "name": {
 | 
			
		||||
                    "type": "string"
 | 
			
		||||
                },
 | 
			
		||||
                "parent_group": {
 | 
			
		||||
                    "$ref": "#/definitions/models.Group"
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,15 @@
 | 
			
		||||
                        "description": "Barcode height",
 | 
			
		||||
                        "name": "height",
 | 
			
		||||
                        "in": "query"
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "maximum": 100,
 | 
			
		||||
                        "minimum": 0,
 | 
			
		||||
                        "type": "integer",
 | 
			
		||||
                        "default": 10,
 | 
			
		||||
                        "description": "Padding around the barcode (included in image size)",
 | 
			
		||||
                        "name": "padding",
 | 
			
		||||
                        "in": "query"
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                "responses": {}
 | 
			
		||||
@@ -303,18 +312,11 @@
 | 
			
		||||
        "models.Group": {
 | 
			
		||||
            "type": "object",
 | 
			
		||||
            "required": [
 | 
			
		||||
                "id",
 | 
			
		||||
                "name"
 | 
			
		||||
            ],
 | 
			
		||||
            "properties": {
 | 
			
		||||
                "id": {
 | 
			
		||||
                    "type": "integer"
 | 
			
		||||
                },
 | 
			
		||||
                "name": {
 | 
			
		||||
                    "type": "string"
 | 
			
		||||
                },
 | 
			
		||||
                "parent_group": {
 | 
			
		||||
                    "$ref": "#/definitions/models.Group"
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 
 | 
			
		||||
@@ -94,14 +94,9 @@ definitions:
 | 
			
		||||
    type: object
 | 
			
		||||
  models.Group:
 | 
			
		||||
    properties:
 | 
			
		||||
      id:
 | 
			
		||||
        type: integer
 | 
			
		||||
      name:
 | 
			
		||||
        type: string
 | 
			
		||||
      parent_group:
 | 
			
		||||
        $ref: '#/definitions/models.Group'
 | 
			
		||||
    required:
 | 
			
		||||
    - id
 | 
			
		||||
    - name
 | 
			
		||||
    type: object
 | 
			
		||||
  models.Runner:
 | 
			
		||||
@@ -195,6 +190,13 @@ paths:
 | 
			
		||||
        minimum: 1
 | 
			
		||||
        name: height
 | 
			
		||||
        type: integer
 | 
			
		||||
      - default: 10
 | 
			
		||||
        description: Padding around the barcode (included in image size)
 | 
			
		||||
        in: query
 | 
			
		||||
        maximum: 100
 | 
			
		||||
        minimum: 0
 | 
			
		||||
        name: padding
 | 
			
		||||
        type: integer
 | 
			
		||||
      produces:
 | 
			
		||||
      - image/png
 | 
			
		||||
      responses: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,11 @@ import (
 | 
			
		||||
//	@Summary		Generate barcodes
 | 
			
		||||
//	@Description	Generate barcodes based on the provided data
 | 
			
		||||
//	@Tags			barcodes
 | 
			
		||||
//	@Param			type	path	string	true	"Barcode type"		Enums(ean13, code128)
 | 
			
		||||
//	@Param			content	path	string	true	"Barcode content"	MinLength(1)
 | 
			
		||||
//	@Param			width	query	int		false	"Barcode width"		Minimum(1)	Maximum(10000) default(1000)
 | 
			
		||||
//	@Param			height	query	int		false	"Barcode height"	Minimum(1)	Maximum(10000) default(1000)
 | 
			
		||||
//	@Param			type	path	string	true	"Barcode type"											Enums(ean13, code128)
 | 
			
		||||
//	@Param			content	path	string	true	"Barcode content"										MinLength(1)
 | 
			
		||||
//	@Param			width	query	int		false	"Barcode width"											Minimum(1)	Maximum(10000)	default(1000)
 | 
			
		||||
//	@Param			height	query	int		false	"Barcode height"										Minimum(1)	Maximum(10000)	default(1000)
 | 
			
		||||
//	@Param			padding	query	int		false	"Padding around the barcode (included in image size)"	Minimum(0)	Maximum(100)	default(10)
 | 
			
		||||
//	@Produce		image/png
 | 
			
		||||
//	@Router			/v1/barcodes/{type}/{content} [get]
 | 
			
		||||
func (h *DefaultHandler) GenerateBarcode(c *fiber.Ctx) error {
 | 
			
		||||
@@ -26,6 +27,7 @@ func (h *DefaultHandler) GenerateBarcode(c *fiber.Ctx) error {
 | 
			
		||||
	// Get the width and height from the query parameters
 | 
			
		||||
	widthStr := c.Query("width", "1000")
 | 
			
		||||
	heightStr := c.Query("height", "1000")
 | 
			
		||||
	paddingStr := c.Query("padding", "10")
 | 
			
		||||
 | 
			
		||||
	// Convert width and height to integers
 | 
			
		||||
	width, err := strconv.Atoi(widthStr)
 | 
			
		||||
@@ -42,8 +44,15 @@ func (h *DefaultHandler) GenerateBarcode(c *fiber.Ctx) error {
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	padding, err := strconv.Atoi(paddingStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
 | 
			
		||||
			"error": "Invalid padding parameter",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Generate the barcode
 | 
			
		||||
	barcode, err := h.BarcodeService.GenerateBarcode(barcodeType, barcodeContent, width, height)
 | 
			
		||||
	barcode, err := h.BarcodeService.GenerateBarcode(barcodeType, barcodeContent, width, height, padding)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
 | 
			
		||||
			"error": err.Error(),
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								main.go
									
									
									
									
									
								
							@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"git.odit.services/lfk/document-server/models"
 | 
			
		||||
	"git.odit.services/lfk/document-server/services"
 | 
			
		||||
	"github.com/gofiber/fiber/v2"
 | 
			
		||||
	"github.com/gofiber/fiber/v2/middleware/cors"
 | 
			
		||||
	"github.com/gofiber/fiber/v2/middleware/keyauth"
 | 
			
		||||
	"github.com/gofiber/swagger"
 | 
			
		||||
	"github.com/redis/go-redis/v9"
 | 
			
		||||
@@ -32,11 +33,21 @@ func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
 | 
			
		||||
 | 
			
		||||
func loadEnv() error {
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("PRODUCION", true)
 | 
			
		||||
	viper.SetDefault("PORT", "3000")
 | 
			
		||||
	viper.SetDefault("APIKEY", "lfk")
 | 
			
		||||
	viper.SetDefault("EVENT_NAME", "Demo Event")
 | 
			
		||||
	viper.SetDefault("CURRENCY_SYMBOL", "€")
 | 
			
		||||
	viper.SetDefault("CARD_SUBTITLE", "Runner Card")
 | 
			
		||||
	viper.SetDefault("CARD_BARCODEFORMAT", "ean13")
 | 
			
		||||
	viper.SetDefault("CARD_BARCODEPREFIX", "")
 | 
			
		||||
	viper.SetDefault("SPONSORING_RECEIPTMINIMUM", 0)
 | 
			
		||||
	viper.SetDefault("SPONSORING_DISCLAIMER", "Disclaimer")
 | 
			
		||||
	viper.SetDefault("SPONSORING_BARCODEFORMAT", "code128")
 | 
			
		||||
	viper.SetDefault("SPONSORING_BARCODEPREFIX", "")
 | 
			
		||||
	viper.SetDefault("CERTIFICATE_FOOTER", "Footer")
 | 
			
		||||
	viper.SetDefault("GOTENBERG_BASEURL", "")
 | 
			
		||||
	viper.SetDefault("REDIS_ADDR", "")
 | 
			
		||||
 | 
			
		||||
	// Load .env file
 | 
			
		||||
	viper.SetConfigFile(".env")
 | 
			
		||||
@@ -54,15 +65,17 @@ func loadEnv() error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Printf("Loaded config: %+v\n", config)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @title						LfK Document Server API
 | 
			
		||||
// @description				This is the API documentation for the LfK Document Server - a tool for pdf generation.
 | 
			
		||||
// @description					This is the API documentation for the LfK Document Server - a tool for pdf generation.
 | 
			
		||||
// @license.name				CC BY-NC-SA 4.0
 | 
			
		||||
// @termsOfService				https://lauf-fuer-kaya.de/datenschutz
 | 
			
		||||
// @contact.name				ODIT.Services UG (haftungsbeschränkt)
 | 
			
		||||
// @contact.url				https://odit.services
 | 
			
		||||
// @contact.url					https://odit.services
 | 
			
		||||
// @contact.email				info@odit.services
 | 
			
		||||
// @securityDefinitions.apiKey	ApiKeyAuth
 | 
			
		||||
// @in							query
 | 
			
		||||
@@ -106,6 +119,8 @@ func main() {
 | 
			
		||||
		Prefork: config.Prod,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	app.Use(cors.New())
 | 
			
		||||
 | 
			
		||||
	// Swagger documentation route
 | 
			
		||||
	app.Get("/swagger/*", swagger.HandlerDefault)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,9 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"image"
 | 
			
		||||
	"image/color"
 | 
			
		||||
	"image/draw"
 | 
			
		||||
	"image/png"
 | 
			
		||||
	"log"
 | 
			
		||||
	"slices"
 | 
			
		||||
@@ -17,7 +20,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type BarcodeService interface {
 | 
			
		||||
	GenerateBarcode(format string, content string, width int, height int) (bytes.Buffer, error)
 | 
			
		||||
	GenerateBarcode(format string, content string, width int, height int, padding int) (bytes.Buffer, error)
 | 
			
		||||
	IsTypeSupported(format string) bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +28,7 @@ type DefaultBarcodeService struct {
 | 
			
		||||
	RedisClient *redis.Client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, width int, height int) (bytes.Buffer, error) {
 | 
			
		||||
func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, width int, height int, padding int) (bytes.Buffer, error) {
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	if !b.IsTypeSupported(format) {
 | 
			
		||||
@@ -33,7 +36,7 @@ func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, w
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b.RedisClient != nil {
 | 
			
		||||
		cachedBarcode, err := b.RedisClient.Get(ctx, fmt.Sprintf("barcode:%s:%s:%d:%d", format, content, width, height)).Result()
 | 
			
		||||
		cachedBarcode, err := b.RedisClient.Get(ctx, fmt.Sprintf("barcode:%s:%s:%d:%d:%d", format, content, width, height, padding)).Result()
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			log.Printf("Cache hit for barcode:%s:%s:%d:%d", format, content, width, height)
 | 
			
		||||
			buf := bytes.Buffer{}
 | 
			
		||||
@@ -66,13 +69,26 @@ func (b *DefaultBarcodeService) GenerateBarcode(format string, content string, w
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scaledCode, err := barcode.Scale(generatedCode, width, height)
 | 
			
		||||
	// Create a white background image
 | 
			
		||||
	bg := image.NewRGBA(image.Rect(0, 0, width, height))
 | 
			
		||||
	white := color.RGBA{255, 255, 255, 255}
 | 
			
		||||
	draw.Draw(bg, bg.Bounds(), &image.Uniform{white}, image.Point{}, draw.Src)
 | 
			
		||||
 | 
			
		||||
	// Calculate the new size for the barcode to fit within the padding
 | 
			
		||||
	newWidth := width - 2*padding
 | 
			
		||||
	newHeight := height - 2*padding
 | 
			
		||||
 | 
			
		||||
	// Scale the barcode to the new size
 | 
			
		||||
	scaledCode, err := barcode.Scale(generatedCode, newWidth, newHeight)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return bytes.Buffer{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Draw the barcode on top of the white background with padding
 | 
			
		||||
	draw.Draw(bg, scaledCode.Bounds().Add(image.Point{padding, padding}), scaledCode, image.Point{}, draw.Over)
 | 
			
		||||
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	err = png.Encode(&buf, scaledCode)
 | 
			
		||||
	err = png.Encode(&buf, bg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return bytes.Buffer{}, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ func (t *DefaultTemplater) GenerateBarcode(code string, format string, prefix st
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := t.BarcodeService.GenerateBarcode(format, code, 1000, 500)
 | 
			
		||||
	buf, err := t.BarcodeService.GenerateBarcode(format, code, 1000, 500, 0)
 | 
			
		||||
 | 
			
		||||
	return base64.StdEncoding.EncodeToString(buf.Bytes()), err
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user