fx build fix
This commit is contained in:
35
api/server/internal/mutil/flrstring/flrstring.go
Normal file
35
api/server/internal/mutil/flrstring/flrstring.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package flrstring
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Constants and variables for random string generation
|
||||
const (
|
||||
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
letterIdxBits = 6
|
||||
letterIdxMask = 1<<letterIdxBits - 1
|
||||
letterIdxMax = 63 / letterIdxBits
|
||||
)
|
||||
|
||||
var src = rand.NewSource(time.Now().UnixNano())
|
||||
|
||||
// createRandString creates a random string with the size of n
|
||||
// See: http://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
|
||||
func CreateRandString(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
|
||||
if remain == 0 {
|
||||
cache, remain = src.Int63(), letterIdxMax
|
||||
}
|
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i--
|
||||
}
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
15
api/server/internal/mutil/imagewriter/imagewriter.go
Normal file
15
api/server/internal/mutil/imagewriter/imagewriter.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package imagewriter
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func WriteImage(w http.ResponseWriter, buffer *[]byte, fileType string) error {
|
||||
w.Header().Set("Content-Type", fileType)
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(*buffer)))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
_, err := w.Write(*buffer)
|
||||
return err
|
||||
}
|
||||
39
api/server/internal/mutil/param/endpoint.go
Normal file
39
api/server/internal/mutil/param/endpoint.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package mutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func AddParam(base string, param string) string {
|
||||
base = strings.TrimSuffix(base, "/")
|
||||
return fmt.Sprintf("%s/{%s}", base, param)
|
||||
}
|
||||
|
||||
func AddAccountRef(base string) string {
|
||||
return AddParam(base, AccountRefName())
|
||||
}
|
||||
|
||||
func AddObjRef(base string) string {
|
||||
return AddParam(base, ObjRefName())
|
||||
}
|
||||
|
||||
func AddOrganizaztionRef(base string) string {
|
||||
return AddParam(base, OrganizationRefName())
|
||||
}
|
||||
|
||||
func AddStatusRef(base string) string {
|
||||
return AddParam(base, StatusRefName())
|
||||
}
|
||||
|
||||
func AddProjectRef(base string) string {
|
||||
return AddParam(base, ProjectRefName())
|
||||
}
|
||||
|
||||
func AddInvitationRef(base string) string {
|
||||
return AddParam(base, InvitationRefName())
|
||||
}
|
||||
|
||||
func AddToken(base string) string {
|
||||
return AddParam(base, TokenName())
|
||||
}
|
||||
135
api/server/internal/mutil/param/getter.go
Normal file
135
api/server/internal/mutil/param/getter.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package mutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/tech/sendico/pkg/mlogger"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func GetParam(r *http.Request, paramName string) string {
|
||||
return chi.URLParam(r, paramName)
|
||||
}
|
||||
|
||||
func GetID(r *http.Request) string {
|
||||
return GetParam(r, "id")
|
||||
}
|
||||
|
||||
func GetAccountID(r *http.Request) string {
|
||||
return GetParam(r, AccountRefName())
|
||||
}
|
||||
|
||||
func GetObjRef(r *http.Request) string {
|
||||
return GetParam(r, ObjRefName())
|
||||
}
|
||||
|
||||
func GetOrganizationID(r *http.Request) string {
|
||||
return GetParam(r, OrganizationRefName())
|
||||
}
|
||||
|
||||
func GetOrganizationRef(r *http.Request) (primitive.ObjectID, error) {
|
||||
return primitive.ObjectIDFromHex(GetOrganizationID(r))
|
||||
}
|
||||
|
||||
func GetStatusID(r *http.Request) string {
|
||||
return GetParam(r, OrganizationRefName())
|
||||
}
|
||||
|
||||
func GetStatusRef(r *http.Request) (primitive.ObjectID, error) {
|
||||
return primitive.ObjectIDFromHex(GetStatusID(r))
|
||||
}
|
||||
|
||||
func GetProjectID(r *http.Request) string {
|
||||
return GetParam(r, ProjectRefName())
|
||||
}
|
||||
|
||||
func GetProjectRef(r *http.Request) (primitive.ObjectID, error) {
|
||||
return primitive.ObjectIDFromHex(GetProjectID(r))
|
||||
}
|
||||
|
||||
func GetInvitationID(r *http.Request) string {
|
||||
return GetParam(r, InvitationRefName())
|
||||
}
|
||||
|
||||
func GetInvitationRef(r *http.Request) (primitive.ObjectID, error) {
|
||||
return primitive.ObjectIDFromHex(GetOrganizationID(r))
|
||||
}
|
||||
|
||||
func GetToken(r *http.Request) string {
|
||||
return GetParam(r, TokenName())
|
||||
}
|
||||
|
||||
// parseFunc is a function type that parses a string to a specific type
|
||||
type parseFunc[T any] func(string) (T, error)
|
||||
|
||||
// getOptionalParam is a generic function that handles optional query parameters
|
||||
func GetOptionalParam[T any](logger mlogger.Logger, r *http.Request, key string, parse parseFunc[T]) (*T, error) {
|
||||
vals := r.URL.Query()
|
||||
s := vals.Get(key)
|
||||
if s == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
val, err := parse(s)
|
||||
if err != nil {
|
||||
logger.Debug("Malformed query parameter", zap.Error(err), zap.String(key, s))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &val, nil
|
||||
}
|
||||
|
||||
// getOptionalInt64Param gets an optional int64 query parameter
|
||||
func GetOptionalInt64Param(logger mlogger.Logger, r *http.Request, key string) (*int64, error) {
|
||||
return GetOptionalParam(logger, r, key, func(s string) (int64, error) {
|
||||
return strconv.ParseInt(s, 10, 64)
|
||||
})
|
||||
}
|
||||
|
||||
func GetLimit(logger mlogger.Logger, r *http.Request) (*int64, error) {
|
||||
return GetOptionalInt64Param(logger, r, "limit")
|
||||
}
|
||||
|
||||
func GetOffset(logger mlogger.Logger, r *http.Request) (*int64, error) {
|
||||
return GetOptionalInt64Param(logger, r, "offset")
|
||||
}
|
||||
|
||||
func GetLimitAndOffset(logger mlogger.Logger, r *http.Request) (*int64, *int64, error) {
|
||||
limit, err := GetLimit(logger, r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
offset, err := GetOffset(logger, r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return limit, offset, nil
|
||||
}
|
||||
|
||||
func GetOptionalBoolParam(logger mlogger.Logger, r *http.Request, key string) (*bool, error) {
|
||||
return GetOptionalParam(logger, r, key, strconv.ParseBool)
|
||||
}
|
||||
|
||||
func GetCascadeParam(logger mlogger.Logger, r *http.Request) (*bool, error) {
|
||||
return GetOptionalBoolParam(logger, r, "cascade")
|
||||
}
|
||||
|
||||
func GetArchiveParam(logger mlogger.Logger, r *http.Request) (*bool, error) {
|
||||
return GetOptionalBoolParam(logger, r, "archived")
|
||||
}
|
||||
|
||||
func GetViewCursor(logger mlogger.Logger, r *http.Request) (*model.ViewCursor, error) {
|
||||
var res model.ViewCursor
|
||||
var err error
|
||||
if res.Limit, res.Offset, err = GetLimitAndOffset(logger, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.IsArchived, err = GetArchiveParam(logger, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
142
api/server/internal/mutil/param/getter_test.go
Normal file
142
api/server/internal/mutil/param/getter_test.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package mutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/tech/sendico/pkg/mlogger"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func TestGetOptionalBoolParam(t *testing.T) {
|
||||
logger := mlogger.Logger(zap.NewNop())
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
expected *bool
|
||||
hasError bool
|
||||
}{
|
||||
{
|
||||
name: "valid true",
|
||||
query: "?param=true",
|
||||
expected: boolPtr(true),
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "valid false",
|
||||
query: "?param=false",
|
||||
expected: boolPtr(false),
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "missing parameter",
|
||||
query: "?other=value",
|
||||
expected: nil,
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid value",
|
||||
query: "?param=invalid",
|
||||
expected: nil,
|
||||
hasError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "http://example.com"+tt.query, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := GetOptionalBoolParam(logger, req, "param")
|
||||
|
||||
if tt.hasError {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
if tt.expected == nil {
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, *tt.expected, *result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOptionalInt64Param(t *testing.T) {
|
||||
logger := mlogger.Logger(zap.NewNop())
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
query string
|
||||
expected *int64
|
||||
hasError bool
|
||||
}{
|
||||
{
|
||||
name: "valid positive number",
|
||||
query: "?param=123",
|
||||
expected: int64Ptr(123),
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "valid negative number",
|
||||
query: "?param=-456",
|
||||
expected: int64Ptr(-456),
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "valid zero",
|
||||
query: "?param=0",
|
||||
expected: int64Ptr(0),
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "missing parameter",
|
||||
query: "?other=value",
|
||||
expected: nil,
|
||||
hasError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid value",
|
||||
query: "?param=invalid",
|
||||
expected: nil,
|
||||
hasError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "http://example.com"+tt.query, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := GetOptionalInt64Param(logger, req, "param")
|
||||
|
||||
if tt.hasError {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
if tt.expected == nil {
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, *tt.expected, *result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions for creating pointers to values
|
||||
func boolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
func int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
44
api/server/internal/mutil/param/helper.go
Normal file
44
api/server/internal/mutil/param/helper.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package mutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
mutilimp "github.com/tech/sendico/server/internal/mutil/param/internal"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type ParamHelper interface {
|
||||
Name() string
|
||||
RefName() string
|
||||
GetID(r *http.Request) string
|
||||
GetRef(r *http.Request) (primitive.ObjectID, error)
|
||||
AddRef(base string) string
|
||||
}
|
||||
|
||||
func CreatePH(resource string) ParamHelper {
|
||||
return mutilimp.CreateImp(resource)
|
||||
}
|
||||
|
||||
type DependentParamHelper struct {
|
||||
p ParamHelper
|
||||
c ParamHelper
|
||||
}
|
||||
|
||||
func (ph *DependentParamHelper) Parent() ParamHelper {
|
||||
return ph.p
|
||||
}
|
||||
|
||||
func (ph *DependentParamHelper) Child() ParamHelper {
|
||||
return ph.c
|
||||
}
|
||||
|
||||
func (ph *DependentParamHelper) AddRef(base string) string {
|
||||
return ph.Parent().AddRef(ph.Child().AddRef(base))
|
||||
}
|
||||
|
||||
func CreateDPH(pRes, cRes string) *DependentParamHelper {
|
||||
return &DependentParamHelper{
|
||||
p: CreatePH(pRes),
|
||||
c: CreatePH(cRes),
|
||||
}
|
||||
}
|
||||
51
api/server/internal/mutil/param/internal/helper.go
Normal file
51
api/server/internal/mutil/param/internal/helper.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package mutilimp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
func addParam(base string, param string) string {
|
||||
base = strings.TrimSuffix(base, "/")
|
||||
return fmt.Sprintf("%s/{%s}", base, param)
|
||||
}
|
||||
|
||||
func _ref(param string) string {
|
||||
return param + "_ref"
|
||||
}
|
||||
|
||||
func getParam(r *http.Request, paramName string) string {
|
||||
return chi.URLParam(r, paramName)
|
||||
}
|
||||
|
||||
type ParamHelper struct {
|
||||
t string
|
||||
}
|
||||
|
||||
func (ph *ParamHelper) Name() string {
|
||||
return ph.t
|
||||
}
|
||||
|
||||
func (ph *ParamHelper) RefName() string {
|
||||
return _ref(ph.Name())
|
||||
}
|
||||
|
||||
func (ph *ParamHelper) GetID(r *http.Request) string {
|
||||
return getParam(r, ph.RefName())
|
||||
}
|
||||
|
||||
func (ph *ParamHelper) GetRef(r *http.Request) (primitive.ObjectID, error) {
|
||||
return primitive.ObjectIDFromHex(ph.GetID(r))
|
||||
}
|
||||
|
||||
func (ph *ParamHelper) AddRef(base string) string {
|
||||
return addParam(base, ph.RefName())
|
||||
}
|
||||
|
||||
func CreateImp(resource string) *ParamHelper {
|
||||
return &ParamHelper{t: resource}
|
||||
}
|
||||
15
api/server/internal/mutil/param/logger.go
Normal file
15
api/server/internal/mutil/param/logger.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package mutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func PLog(ph ParamHelper, r *http.Request) zap.Field {
|
||||
return zap.String(ph.Name(), ph.GetID(r))
|
||||
}
|
||||
|
||||
func PLogType(ph ParamHelper) zap.Field {
|
||||
return zap.String("object", ph.Name())
|
||||
}
|
||||
33
api/server/internal/mutil/param/names.go
Normal file
33
api/server/internal/mutil/param/names.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package mutil
|
||||
|
||||
func _ref(param string) string {
|
||||
return param + "_ref"
|
||||
}
|
||||
|
||||
func AccountRefName() string {
|
||||
return _ref("account")
|
||||
}
|
||||
|
||||
func ObjRefName() string {
|
||||
return _ref("obj")
|
||||
}
|
||||
|
||||
func OrganizationRefName() string {
|
||||
return _ref("org")
|
||||
}
|
||||
|
||||
func StatusRefName() string {
|
||||
return _ref("status")
|
||||
}
|
||||
|
||||
func ProjectRefName() string {
|
||||
return _ref("project")
|
||||
}
|
||||
|
||||
func InvitationRefName() string {
|
||||
return _ref("invitation")
|
||||
}
|
||||
|
||||
func TokenName() string {
|
||||
return "token"
|
||||
}
|
||||
11
api/server/internal/mutil/param/ref.go
Normal file
11
api/server/internal/mutil/param/ref.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package mutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
func GetAccountRef(r *http.Request) (primitive.ObjectID, error) {
|
||||
return primitive.ObjectIDFromHex(GetAccountID(r))
|
||||
}
|
||||
15
api/server/internal/mutil/time/go/gotime.go
Normal file
15
api/server/internal/mutil/time/go/gotime.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package mutil
|
||||
|
||||
import "time"
|
||||
|
||||
func ToDate(t time.Time) string {
|
||||
return t.Format(time.DateOnly)
|
||||
}
|
||||
|
||||
func ToTime(t time.Time) string {
|
||||
return t.Format(time.TimeOnly)
|
||||
}
|
||||
|
||||
func ToDateTime(t time.Time) string {
|
||||
return t.Format(time.DateTime)
|
||||
}
|
||||
Reference in New Issue
Block a user