Files
backend_fiesta/services/tenantProfile.go
2026-09-01 12:01:43 +05:30

76 lines
2.5 KiB
Go

package services
import (
"errors"
"strings"
)
// What a merchant is allowed to change about their own business.
//
// An allowlist, and it has to be one. The obvious implementation — hand the
// parsed body to GORM's `Updates` — would let anyone who can reach the endpoint
// set `approved`, `status`, `partnerid`, `partneruserid`, `moduleid`,
// `configid` or `tenanttoken` on their own record: approve themselves onto the
// platform, move themselves under another partner, or reassign their billing.
// None of those belong to the merchant, and none of them are things a UI would
// ever send, which is exactly what makes the omission easy to miss.
//
// So the fields are named here, once, and the repository writes nothing it is
// not given. Anything absent from this map is untouched rather than blanked —
// a profile form that renders four fields must not erase the twenty it did not.
//
// `tenantid` is deliberately absent too: it identifies the row, it is never a
// value to be written.
var editableTenantFields = map[string]bool{
// What a shopper sees.
"tenantname": true,
"tenantimage": true,
"tenantinfo": true,
// How to reach the business.
"primaryemail": true,
"primarycontact": true,
"companyname": true,
// Where it is.
"address": true,
"suburb": true,
"city": true,
"state": true,
"postcode": true,
"latitude": true,
"longitude": true,
// Legal and trading terms.
"registrationno": true,
"licenseno": true,
"minorder": true,
"subcategoryid": true,
}
// TenantProfileUpdate reduces a request to the fields a merchant may set.
//
// Returns an error rather than an empty map when nothing survives: a write that
// changes nothing and reports success is indistinguishable from one that
// worked, and the caller would go on believing their licence number was saved.
func TenantProfileUpdate(fields map[string]any) (map[string]any, error) {
clean := make(map[string]any, len(fields))
for key, value := range fields {
lower := strings.ToLower(strings.TrimSpace(key))
if !editableTenantFields[lower] {
continue
}
// A blank string is "not supplied", not "erase it". The profile form
// sends every field it renders on every save, so honouring blanks would
// let a half-filled form wipe an address somebody typed last month.
if text, ok := value.(string); ok && strings.TrimSpace(text) == "" {
continue
}
clean[lower] = value
}
if len(clean) == 0 {
return nil, errors.New("nothing to update — no editable field was supplied")
}
return clean, nil
}