feat: QR Codes (#226)

* code gen updates

* qrcode support

* remove opacity on toast

* update item view to use tab-like pages

* adjust view for cards

* fix old API calls for ioutils

* move embed

* extract QR code

* add docs for QR codes

* add QR code
This commit is contained in:
Hayden 2023-01-18 20:44:06 -09:00 committed by GitHub
parent f532b39c46
commit c19fe94c08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
88 changed files with 3151 additions and 6454 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,67 @@
package v1
import (
"bytes"
"image/png"
"io"
"net/http"
"github.com/hay-kot/homebox/backend/internal/sys/validate"
"github.com/hay-kot/homebox/backend/pkgs/server"
"github.com/yeqown/go-qrcode/v2"
"github.com/yeqown/go-qrcode/writer/standard"
_ "embed"
)
//go:embed assets/QRIcon.png
var qrcodeLogo []byte
// HandleGenerateQRCode godoc
//
// @Summary Encode data into QRCode
// @Tags Items
// @Produce json
// @Param data query string false "data to be encoded into qrcode"
// @Success 200 {string} string "image/jpeg"
// @Router /v1/qrcode [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGenerateQRCode() server.HandlerFunc {
const MaxLength = 4_296 // assume alphanumeric characters only
return func(w http.ResponseWriter, r *http.Request) error {
data := r.URL.Query().Get("data")
image, err := png.Decode(bytes.NewReader(qrcodeLogo))
if err != nil {
panic(err)
}
if len(data) > MaxLength {
return validate.NewFieldErrors(validate.FieldError{
Field: "data",
Error: "max length is 4,296 characters exceeded",
})
}
qrc, err := qrcode.New(data)
if err != nil {
return err
}
toWriteCloser := struct {
io.Writer
io.Closer
}{
Writer: w,
Closer: io.NopCloser(nil),
}
qrwriter := standard.NewWithWriter(toWriteCloser, standard.WithLogoImage(image))
// Return the QR code as a jpeg image
w.Header().Set("Content-Type", "image/jpeg")
w.Header().Set("Content-Disposition", "attachment; filename=qrcode.jpg")
return qrc.Save(qrwriter)
}
}

View file

@ -119,6 +119,12 @@ func (a *app) mountRoutes(repos *repo.AllRepos) {
a.server.Get(v1Base("/asset/{id}"), v1Ctrl.HandleAssetGet(), userMW...)
// Asset-Like endpoints
a.server.Get(
v1Base("/qrcode"),
v1Ctrl.HandleGenerateQRCode(),
a.mwAuthToken, a.mwRoles(RoleModeOr, authroles.RoleUser.String(), authroles.RoleAttachments.String()),
)
a.server.Get(
v1Base("/items/{id}/attachments/{attachment_id}"),
v1Ctrl.HandleItemAttachmentGet(),

View file

@ -1146,6 +1146,38 @@ const docTemplate = `{
}
}
},
"/v1/qrcode": {
"get": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Items"
],
"summary": "Encode data into QRCode",
"parameters": [
{
"type": "string",
"description": "data to be encoded into qrcode",
"name": "data",
"in": "query"
}
],
"responses": {
"200": {
"description": "image/jpeg",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/status": {
"get": {
"produces": [

View file

@ -1138,6 +1138,38 @@
}
}
},
"/v1/qrcode": {
"get": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"Items"
],
"summary": "Encode data into QRCode",
"parameters": [
{
"type": "string",
"description": "data to be encoded into qrcode",
"name": "data",
"in": "query"
}
],
"responses": {
"200": {
"description": "image/jpeg",
"schema": {
"type": "string"
}
}
}
}
},
"/v1/status": {
"get": {
"produces": [

View file

@ -1301,6 +1301,25 @@ paths:
summary: updates a location
tags:
- Locations
/v1/qrcode:
get:
parameters:
- description: data to be encoded into qrcode
in: query
name: data
type: string
produces:
- application/json
responses:
"200":
description: image/jpeg
schema:
type: string
security:
- Bearer: []
summary: Encode data into QRCode
tags:
- Items
/v1/status:
get:
produces: