This commit is contained in:
2026-09-25 16:18:53 +05:30
parent 7fdcc92528
commit 090e9c0c2f
3 changed files with 124 additions and 10 deletions

View File

@@ -771,6 +771,20 @@ func posClaimError(c *fiber.Ctx, err error) error {
// once the console can hold a session.
// posWebScope reads and checks the tenant and outlet a console request names.
// posTenantScope is the guard for things that belong to a whole business
// rather than to one of its shops — shift windows, so far.
//
// No ownership query, because there is nothing to own: `middleware.WebAuth`
// pins the tenant from the signed session and refuses a request naming another
// one, so reaching here with a tenant id at all means it is this caller's.
// Naming an outlet is what needs checking, and that is `posWebScope` below.
func (ctl *PosController) posTenantScope(tenantID int) error {
if tenantID <= 0 {
return fmt.Errorf("tenantid is required")
}
return nil
}
func (ctl *PosController) posWebScope(tenantID, locationID int) error {
if tenantID <= 0 {
return fmt.Errorf("tenantid is required")
@@ -921,9 +935,18 @@ func (ctl *PosController) WebListStaffShifts(c *fiber.Ctx) error {
tenantID, _ := strconv.Atoi(strings.TrimSpace(c.Query("tenantid")))
locationID, _ := strconv.Atoi(strings.TrimSpace(c.Query("locationid")))
if err := ctl.posWebScope(tenantID, locationID); err != nil {
// Tenant-scoped, because a shift belongs to the business rather than to one
// of its shops. An outlet may still be named to narrow the list, and is
// checked for ownership when it is — omitting it is not a way to read
// somebody else's, because the tenant comes from the signed session.
if err := ctl.posTenantScope(tenantID); err != nil {
return posBadRequest(c, err)
}
if locationID > 0 {
if err := ctl.posWebScope(tenantID, locationID); err != nil {
return posBadRequest(c, err)
}
}
shifts, err := ctl.posService.ListStaffShifts(tenantID, locationID,
strings.EqualFold(c.Query("include_inactive"), "true"))
@@ -944,9 +967,19 @@ func (ctl *PosController) WebCreateStaffShift(c *fiber.Ctx) error {
return posBadRequest(c, fmt.Errorf("invalid request body"))
}
if err := ctl.posWebScope(req.Tenantid, req.Locationid); err != nil {
// A shift with no outlet belongs to the tenant and every branch it owns,
// which is the ordinary case — a business that works 07:00–15:00 works
// those hours at every shop, and entering them per outlet is how the third
// branch quietly ends up on 07:00–15:30. An outlet is named only when one
// shop really does differ, and is checked for ownership then.
if err := ctl.posTenantScope(req.Tenantid); err != nil {
return posBadRequest(c, err)
}
if req.Locationid > 0 {
if err := ctl.posWebScope(req.Tenantid, req.Locationid); err != nil {
return posBadRequest(c, err)
}
}
shift, err := ctl.posService.CreateStaffShift(req.Tenantid, req.Locationid, req)
if err != nil {