File, Open: a search dialog that shows only what you may see
estate-agent-software feature permissions search windows-client
The last workshop report ended with an announcement: a real document open dialog with a search over everything you are allowed to see. The background is a small embarrassment. Our estate agent software is a desktop application on .NET, and the interface comes from an in-house kit originally built for file-based documents. The open button on the file page therefore did until today what it always does in that kit: it opened a file dialog. Only our documents are not files. A property website, a template, a contact — those are rows on the server, and a file dialog finds none of them.
This week we rehung the button. That sounds like an afternoon's work. It was four components, and each had a decision of its own.
A search term on every record
A search needs something it can search in. Until now every data type knew only its display name, and a search across contacts, websites and templates at once would have meant one query per type. Now every record carries a search term — a column on the shared foundation of all data types. The server calculates it on saving: for the contact from name, e-mail address, phone numbers and the companies, for the property from property numbers and title, for the website from name and address.
And because calculating is not always enough, there is a switch. Whoever ticks manual in the properties dialog writes the search term themselves — “neighbour of the corner house” then sits on a contact you would otherwise never find again. Untick it and the next save restores the calculated default. One column, one switch, no second field.
One decision underneath was less obvious: the default of the foundation is empty, not the display name. The display name of a company member resolves the company, that of a file its folder — and saving runs on a worker thread on which the database layer tolerates no such lazy loads. Three tests showed us that before a user could see it. Now every searchable data type names its own fields, and whatever would have to be loaded on saving it remembers beforehand.
The search runs on the server
The desktop client reads its data through a read tunnel that enforces user permissions — that was the subject of the last report. The new search deliberately does not go through that tunnel but is an endpoint of its own: a single query over the shared table of all data types, filtered by tenant, by the types being searched and by the record permissions of the role. Whoever may not see a property does not find it through the detour of the search either. That is not a second permission check, it is the same rule in the same place.
The search works word by word: all words must occur, * stands for any characters, ? for exactly one. “Meier Berlin” finds the contact whose company sits in Berlin. “LoftPark”* finds the title whose middle you have forgotten.
Recently opened, on every machine
The second part of the dialog is the list of recently opened documents. The kit would have kept it locally, as a file in the Windows user's profile. We put it on the server, per user, twenty entries. An agent who works at the desk in the morning and on the notebook in the afternoon sees the same list on both. And because the server resolves every row again on reading, a document disappears from the list as soon as it is deleted or the team has assigned it to somebody else. The list never names anything you could not open.
The list sits in two places: in the dialog as long as the search field is empty, and in the drop-down menu of the open button itself. One click and the website from this morning is back.
Documents now go by their stable name
A side effect that matters more to us than the dialog: until now an open document remembered its website through the running number from the database. That is enough as long as the database stays the same. For a recent list meant to survive a database rebuild it is not enough. Website and template documents now carry the globally unique key of their record, and the modules register their document types in a central place — the dialog knows not a single module by name. When contact, company and property get documents of their own in the next step, those are one entry each in that registration, not a rebuild of the dialog.
Three finds from the live test
The first: the search found nothing. Nothing at all. The new column was there but empty for 26,000 legacy rows, because the search term only comes into being on the next save. So a recalculation at server start — which on the second run still found nothing, because the database had filled the new switch on old rows not with off but with nothing. A criterion that reads nothing as off, and the list filled up.
The second: a copied template was found, the delivered one was not. Delivered templates belong to a shared group that belongs to no estate agent office and that the read tunnel silently adds for every user. The search did not add it. Now it draws the same circle as the tunnel — and the standard template is back in the list.
The third was not a find of this week at all but one from last: a test in the branch was red ever since the root folder of a tenant resists every assignment. The test had hung its folder directly under the storage root and was thereby that root itself. Whoever takes over a branch takes over its red tests; we reproduced it with a tenant root above the team folder.
The balance in numbers
- 1 column and 1 switch on the foundation of all data types, 6 data types with a search term of their own
- 2 new endpoints: search and recent list, both with the same permissions as the tunnel
- 5 properties dialogs with the search term field and the manual tick
- 1 dialog behind file, open that knows no module by name
- over 3,500 automated tests, all green — three of which protected us from ourselves this week
What users see of it: an open button that does what it promises. Type, find, open — and only what your own role may see. A single agent notices nothing of the data separation. An estate agent office with thirty people notices that a colleague's search does not spit out their contacts.
The next step already stands in the registration of the document types: contact, company, lead and property as documents of their own, with properties for the quick dialog and open for the whole file.