2021-04-28 21:08:24 +02:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"regexp"
|
|
|
|
"sort"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// FieldList is a parameter type to represent a list of fields in the database
|
|
|
|
// to return. It can be used with query.FieldListToSelect to build a
|
|
|
|
// select clause to return the data that was requested.
|
|
|
|
FieldList struct {
|
|
|
|
fields map[string]bool
|
|
|
|
}
|
2021-05-07 10:17:05 +02:00
|
|
|
// FieldMap is a set of key/value pairs.
|
|
|
|
// It can be used to with query.FieldMapToUpdate to build a
|
|
|
|
// set clause for an update statement.
|
|
|
|
FieldMap struct {
|
|
|
|
fields map[string]interface{}
|
|
|
|
}
|
2021-04-28 21:08:24 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// fieldIdentifier filters field names to allow only sane values
|
|
|
|
// and at the same time make them save for database queries.
|
2021-05-07 10:17:05 +02:00
|
|
|
fieldIdentifier = regexp.MustCompile(`\A[a-zA-Z]+([a-zA-Z0-9_\-.]*)`)
|
2021-04-28 21:08:24 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func NewFieldList(fields ...string) FieldList {
|
|
|
|
fl := FieldList{
|
|
|
|
fields: map[string]bool{},
|
|
|
|
}
|
|
|
|
for _, field := range fields {
|
|
|
|
fl.fields[field] = true
|
|
|
|
}
|
|
|
|
return fl
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fl *FieldList) UnmarshalJSON(raw []byte) error {
|
|
|
|
fields := []string{}
|
|
|
|
if err := json.Unmarshal(raw, &fields); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
fl.fields = map[string]bool{}
|
|
|
|
for _, field := range fields {
|
|
|
|
if !fieldIdentifier.Match([]byte(field)) {
|
|
|
|
return fmt.Errorf("`%s` is not an allowed field name. Allowed is only alpha numerical", field)
|
|
|
|
}
|
|
|
|
fl.fields[field] = true
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Contains returns true, when the string is found in the list.
|
|
|
|
func (fl FieldList) Contains(in string) bool {
|
|
|
|
_, found := fl.fields[in]
|
|
|
|
return found
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fields returns a sorted list of the requested fields.
|
|
|
|
func (fl FieldList) Fields() []string {
|
|
|
|
res := []string{}
|
|
|
|
for name, _ := range fl.fields {
|
|
|
|
res = append(res, name)
|
|
|
|
}
|
|
|
|
sort.Strings(res)
|
|
|
|
return res
|
|
|
|
}
|
2021-05-07 10:17:05 +02:00
|
|
|
|
|
|
|
// NewFieldMap builds a FieldMap with the provided defaults.
|
|
|
|
func NewFieldMap(fields map[string]interface{}) FieldMap {
|
|
|
|
return FieldMap{fields: fields}
|
|
|
|
}
|
|
|
|
|
2021-05-08 22:40:02 +02:00
|
|
|
func (fm *FieldMap) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(fm.fields)
|
|
|
|
}
|
|
|
|
|
2021-05-07 10:17:05 +02:00
|
|
|
// UnmarshalJSON implements the json decoding interface so that it can be used with
|
|
|
|
// with the request parsing functions.
|
|
|
|
func (fm *FieldMap) UnmarshalJSON(raw []byte) error {
|
|
|
|
fields := map[string]interface{}{}
|
|
|
|
if err := json.Unmarshal(raw, &fields); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for k, _ := range fields {
|
|
|
|
if !fieldIdentifier.Match([]byte(k)) {
|
|
|
|
return fmt.Errorf("`%s` is not an allowed field name. Allowed is only alpha numerical", k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fm.fields = fields
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-05-09 21:22:52 +02:00
|
|
|
func (fm FieldMap) Contains(key string) bool {
|
|
|
|
_, found := fm.fields[key]
|
|
|
|
return found
|
|
|
|
}
|
|
|
|
|
2021-05-08 22:40:02 +02:00
|
|
|
// Set adds a key to the field map.
|
|
|
|
func (fm FieldMap) Set(key string, val interface{}) {
|
|
|
|
fm.fields[key] = val
|
|
|
|
}
|
|
|
|
|
2021-05-09 21:22:52 +02:00
|
|
|
func (fm FieldMap) Delete(key string) {
|
|
|
|
delete(fm.fields, key)
|
|
|
|
}
|
|
|
|
|
2021-05-07 10:17:05 +02:00
|
|
|
// Fields returns all key/value pairs.
|
|
|
|
func (fm FieldMap) Fields() map[string]interface{} {
|
|
|
|
return fm.fields
|
|
|
|
}
|
|
|
|
|
|
|
|
// Size returns the number of keys.
|
|
|
|
func (fm FieldMap) Size() int {
|
|
|
|
return len(fm.fields)
|
|
|
|
}
|