guide changes
This commit is contained in:
75
services/tenantProfile.go
Normal file
75
services/tenantProfile.go
Normal file
@@ -0,0 +1,75 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user