Suppose you have entities A, B, C, and D.
- D refers to C
- C refers to B
- B refers to A
In addition, the user is allowed to work with D if the user owns A.
In a certain state of the application, you include a link to a page that accesses D. Thus, you include a D ID as a GET or POST parameter.
If the user clicks on the link, the application retrieves the D ID and starts working with D.
Simple applications use URLs such as [modulo URL-rewriting]:
http:
How to check if the user is allowed to work with D?
A) The obvious solution would be the following: Given D, find C, then find B and finally find A. If the chain breaks somewhere, access to D will be denied. Unfortunately, this requires - if trivially implemented - 4 access to the database, not just A.
B) Another solution would be to save the D ID in the current session in the set of available objects that will be used on the next page for visualization. p>
C) Alternatively, the GET and POST parameters could be encrypted . In each page request, the first operation would be to decrypt the request parameters. If the decryption operation failed, access will be denied.
D) Or, at infinity, the hash of all links on all pages , hold a map in a session that associates hashes with URLs and writes only hashes to web pages,
E) Finally, you can save links to A, B and C in D, links to A and B in C, links to A in B. Thus, at each level it is able to quickly find the root object .
What is your decision in this situation? And why?
Although I have included the PHP tag, I do not want to focus this question on the language. I would be happy to receive general suggestions. Or solutions that are already implemented, for example, ORM .
UPDATE-1
Finally, I chose D) .
General principle:
Make sure that the identifiers of some subordinate objects are always transmitted in a safe / reliable way. Thus, a third party is not able to change their meanings.
Details:
This option provides many design benefits:
Firstly, identifiers or other parameters of linked pages never reach the browser. Instead
http:
most pages are linked this way
http:
All parameters of the next executable page are completely stored inside the user session .
Since all page parameters are stored inside a user session, much less verification is required . In particular, the above relational dependency checks are no longer used. If something is in a user session, it was placed with a previously trusted dialog step .
In addition, even force the user to call only this link on the current page displayed . Each time they call a link, the application can cancel all other links on the page. Thus, users will not be able to open pages in multiple windows and think that they see two different "states" of the application. If they call the link twice, the application may present an error message.
Finally, you can directly install something that I would call sub-workflow dialogs: you started the dialog by pushing the current URL of the page onto the continuation stack in the session and opening the edit dialog. The user can either streamline or intentionally cancel the dialog workflow. The link to cancel the workflow can automatically be displayed as a custom option if the continuation stack is not empty.
By keeping the continuation on the stack in the session, it is completely isolated from the current dialog step. The conversation step does not even know about its caller.
Having wrapped the functionality inside small manager calls, the subprocess finally calls FlowManager :: finishFlow (). This call pushes the continuation from the stack and redirects the browser to this page - effectively returning to the point where the workflow began .
Since we use a stack of continuations, you can even run slave processes that are subordinate to other sub-workflows .