guide changes
This commit is contained in:
100
services/tenantProfile_test.go
Normal file
100
services/tenantProfile_test.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package services
|
||||
|
||||
import "testing"
|
||||
|
||||
/*
|
||||
The tenants table had no write path at all, so a merchant could never change
|
||||
their own shop's photo, licence number or contact — measured across 200 tenants:
|
||||
18 had an image, none had a licence.
|
||||
|
||||
Adding one is where the risk is. `tenants` carries platform-controlled columns
|
||||
next to merchant-owned ones — `approved`, `status`, `partnerid`, `partneruserid`,
|
||||
`moduleid`, `configid`, `tenanttoken` — and the obvious implementation, handing
|
||||
the parsed body to GORM, would let anyone reaching the endpoint approve
|
||||
themselves onto the platform or move themselves under a different partner. A UI
|
||||
would never send those fields, which is what makes the hole easy to leave open.
|
||||
*/
|
||||
|
||||
func TestAMerchantCannotApproveThemselves(t *testing.T) {
|
||||
clean, err := TenantProfileUpdate(map[string]any{
|
||||
"tenantimage": "https://example.com/shop.jpg",
|
||||
"approved": 1,
|
||||
"status": "Active",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("TenantProfileUpdate: %v", err)
|
||||
}
|
||||
for _, forbidden := range []string{"approved", "status"} {
|
||||
if _, present := clean[forbidden]; present {
|
||||
t.Errorf("%q survived the allowlist", forbidden)
|
||||
}
|
||||
}
|
||||
if clean["tenantimage"] != "https://example.com/shop.jpg" {
|
||||
t.Errorf("the legitimate field was dropped: %+v", clean)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOwnershipAndBillingColumnsAreNotEditable(t *testing.T) {
|
||||
_, err := TenantProfileUpdate(map[string]any{
|
||||
"partnerid": 9,
|
||||
"partneruserid": 9,
|
||||
"moduleid": 3,
|
||||
"configid": 2,
|
||||
"tenanttoken": "stolen",
|
||||
"tenantid": 1,
|
||||
})
|
||||
// Every field was refused, so nothing is left to write — and that must be
|
||||
// an error, not a silent success.
|
||||
if err == nil {
|
||||
t.Fatal("a request of nothing but forbidden fields was accepted")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
A profile form sends every field it renders on every save. If a blank meant
|
||||
"erase", opening the form and saving one change would wipe everything the form
|
||||
does not show — an address typed last month, a licence added by somebody else.
|
||||
*/
|
||||
func TestABlankFieldIsNotAnInstructionToErase(t *testing.T) {
|
||||
clean, err := TenantProfileUpdate(map[string]any{
|
||||
"licenseno": "12345678901234",
|
||||
"address": " ",
|
||||
"city": "",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("TenantProfileUpdate: %v", err)
|
||||
}
|
||||
if _, present := clean["address"]; present {
|
||||
t.Error("a whitespace-only value was treated as a change")
|
||||
}
|
||||
if _, present := clean["city"]; present {
|
||||
t.Error("an empty value was treated as a change")
|
||||
}
|
||||
if clean["licenseno"] != "12345678901234" {
|
||||
t.Errorf("the real change was lost: %+v", clean)
|
||||
}
|
||||
}
|
||||
|
||||
// Zero is a real minimum order and a real subcategory id is not a string, so
|
||||
// the blank rule must apply to text only.
|
||||
func TestANumericZeroIsStillAChange(t *testing.T) {
|
||||
clean, err := TenantProfileUpdate(map[string]any{"minorder": 0})
|
||||
if err != nil {
|
||||
t.Fatalf("TenantProfileUpdate: %v", err)
|
||||
}
|
||||
if value, present := clean["minorder"]; !present || value != 0 {
|
||||
t.Errorf("a minimum order of zero was dropped: %+v", clean)
|
||||
}
|
||||
}
|
||||
|
||||
// Case and stray whitespace in a key are a client's problem, not a reason to
|
||||
// silently ignore a field the merchant filled in.
|
||||
func TestFieldNamesAreMatchedLeniently(t *testing.T) {
|
||||
clean, err := TenantProfileUpdate(map[string]any{" TenantImage ": "x.jpg"})
|
||||
if err != nil {
|
||||
t.Fatalf("TenantProfileUpdate: %v", err)
|
||||
}
|
||||
if clean["tenantimage"] != "x.jpg" {
|
||||
t.Errorf("want the field normalised onto its column, got %+v", clean)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user