Let an admin create till staff from the console, through the same code
An admin sets a shop up from a browser; a supervisor adds a cashier at the counter. Both had to be possible, and only the second one was. So the console gets createposuser / updateposuser / getposusers / deleteposuser, under both /v1/web/tenants and /v1/mob/tenants — calling the same service methods `/pos/users` calls. Not a parallel implementation: a supervisor created from a browser is the same row, with the same PIN rules, the same duplicate check and the same identity-column allocation, as one created at a till. Two paths writing one table is precisely how the two stop matching, and this codebase already had that happen once. configid is inferred rather than asked for. It is a number nobody looks up, it varies per tenant — 1087's accounts are spread across 1, 6 and 15 — and getting it wrong creates somebody who cannot sign into the portal their colleagues use and is invisible to half the platform's queries. /posroles is served rather than left to the console to hardcode. A console that knew supervisor was 7 would be wrong the day that changed and would have no way to find out. The outlet is the real difference between the two doors. A terminal proves it with a signed token; the console asserts it, and is checked against the tenant before anything is written. That is weaker, and it is worth being plain about: these mint till credentials on an unauthenticated request, exactly like every other route in the /v1/web and /v1/mob groups, because there is no auth middleware on the web API at all. Documented as the weakest point in the design and flagged to move behind a session guard once the console can hold one. The terminal routes are untouched by it. Proven in a rolled-back transaction against live data: the console creates a supervisor at 1135, that supervisor signs in by PIN with can_manage_staff true, the till's /pos/staff sees them alongside the two created at the counter, and 0451, 1234 and a duplicate PIN are each refused with the same message the terminal gives. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
56
POS_LOGIN.md
56
POS_LOGIN.md
@@ -325,6 +325,62 @@ with one tap.
|
||||
|
||||
---
|
||||
|
||||
## Creating staff from the web console
|
||||
|
||||
The same staff management, for the screen an admin actually uses. Registered
|
||||
under both `/v1/web/tenants` and `/v1/mob/tenants`.
|
||||
|
||||
```
|
||||
GET /v1/web/tenants/posroles
|
||||
GET /v1/web/tenants/getposusers?tenantid=1087&locationid=1135
|
||||
POST /v1/web/tenants/createposuser
|
||||
PUT /v1/web/tenants/updateposuser
|
||||
DELETE /v1/web/tenants/deleteposuser?tenantid=1087&locationid=1135&userid=9189
|
||||
```
|
||||
|
||||
`createposuser` takes the same body as `/pos/users`, plus the outlet — the
|
||||
console has no session token, so it has to name one:
|
||||
|
||||
```json
|
||||
{
|
||||
"tenantid": 1087,
|
||||
"locationid": 1135,
|
||||
"full_name": "Asha Kumar",
|
||||
"role": "cashier",
|
||||
"pin": "4821"
|
||||
}
|
||||
```
|
||||
|
||||
**These run the same service calls as `/pos/users`.** A supervisor created from
|
||||
a browser is the same row, with the same rules applied, as one created at a
|
||||
counter — same PIN validation, same duplicate check, same identity-column
|
||||
allocation. That is the point of them: two paths writing one table is how the
|
||||
two stop matching.
|
||||
|
||||
`configid` is never asked for. It is inferred from whichever value the tenant's
|
||||
existing accounts carry — a number nobody looks up, that varies per tenant (1087
|
||||
is spread across 1, 6 and 15), and that silently creates an account nobody can
|
||||
find if it is wrong.
|
||||
|
||||
`GET /posroles` returns the two roles with their ids and labels, so a console
|
||||
offering the choice never has to know that supervisor is `7`.
|
||||
|
||||
### :red_circle: These are unauthenticated
|
||||
|
||||
Like every other route in the `/v1/web` and `/v1/mob` groups — there is no auth
|
||||
middleware anywhere on the web API. The outlet is checked against the tenant
|
||||
before anything is written, so a caller cannot create staff at a shop that is
|
||||
not theirs *given a tenant id* — but nothing proves the caller is that tenant.
|
||||
|
||||
So this mints till credentials on an unauthenticated request. It is consistent
|
||||
with the rest of the platform, and it is still the weakest point in this design.
|
||||
They should move behind a session guard as soon as the console can hold one.
|
||||
|
||||
The terminal routes are not affected: `/pos/users` proves its outlet with a
|
||||
signed token.
|
||||
|
||||
---
|
||||
|
||||
## Using the token
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user