package handler import ( "bytes" "context" "encoding/json" "fmt" "time" "github.com/google/uuid" "github.com/micro/micro/v3/service/config" "github.com/micro/micro/v3/service/errors" log "github.com/micro/micro/v3/service/logger" "github.com/micro/micro/v3/service/store" "github.com/micro/services/pkg/tenant" qr "github.com/micro/services/qr/proto" "github.com/skip2/go-qrcode" ) const ( prefixByTenant = "qrByTenant" defaultCodeSize = 256 ) type QrCode struct { Filename string `json:"filename"` Created int64 `json:"created"` Text string `json:"text"` } type Qr struct { cdnPrefix string } func New() *Qr { v, err := config.Get("micro.qr.cdnprefix") if err != nil { log.Fatalf("Failed to get CDN prefix %s", err) } pref := v.String("") if len(pref) == 0 { log.Fatalf("Failed to get CDN prefix") } return &Qr{cdnPrefix: pref} } func (q *Qr) Generate(ctx context.Context, request *qr.GenerateRequest, response *qr.GenerateResponse) error { if len(request.Text) == 0 { return errors.BadRequest("qr.generate", "Missing parameter text") } ten, ok := tenant.FromContext(ctx) if !ok { log.Errorf("Error retrieving tenant") return errors.Unauthorized("qr.generate", "Unauthorized") } size := defaultCodeSize if request.Size > 0 { size = int(request.Size) } qrc, err := qrcode.Encode(request.Text, qrcode.Medium, size) if err != nil { log.Errorf("Error generating QR code %s", err) return errors.InternalServerError("qr.generate", "Error while generating QR code") } nsPrefix := "micro/qr/" + ten fileName := fmt.Sprintf("%s.png", uuid.New().String()) if err := store.DefaultBlobStore.Write( fileName, bytes.NewBuffer(qrc), store.BlobContentType("image/png"), store.BlobPublic(true), store.BlobNamespace(nsPrefix)); err != nil { log.Errorf("Error saving QR code to blob store %s", err) return errors.InternalServerError("qr.generate", "Error while generating QR code") } // store record of it rec := QrCode{ Filename: fileName, Created: time.Now().Unix(), Text: request.Text, } b, _ := json.Marshal(&rec) if err := store.Write(&store.Record{ Key: fmt.Sprintf("%s/%s/%s", prefixByTenant, nsPrefix, fileName), Value: b, }); err != nil { log.Errorf("Error saving QR code record %s", err) return errors.InternalServerError("qr.generate", "Error while generating QR code") } response.Qr = fmt.Sprintf("%s/%s/%s", q.cdnPrefix, nsPrefix, rec.Filename) return nil }