I am not a professional web developer, however I dabbled in php in high school. I am currently working on updating the website for one of the organizations I belong to in college. I really do not have a succinct way to ask my quesetion, so I will give an example:
For the offices in our organization, the tables are something like this:
officeid_officename
+------------+------------+
| officeid | officename |
+------------+------------+
| 1 | president |
| ... | ... |
+------------+------------+
officeid_memberid
+------------+----------+
| officeid | memberid |
+------------+----------+
| 1 | 234 |
| ... | ... |
+------------+----------+
memberid_memberdata
+------------+------------+-----+
| memberid | membername | ... |
+------------+------------+-----+
| ... | ... | ... |
| 234 | John Smith | ... |
| ... | ... | ... |
+------------+------------+-----+
As far as I can tell, this would be a proper design for the tables because it allows 1) For office names to be arbitrarily changed (e.g. If “President” were to become “Supreme Overlord”) 2) it allows for members to arbitrarily be added to and removed from offices 3) in the end the data about each member can change without the member’s link to an office being affected.
The issue I have is, in the code I am writing, I have authorization that depends on what offices a member holds. I can think of three options of representing what offices are allowed to perform what actions.
1) Use “President”, etc. as the identifier to check for (e.g. if($officename === "president") { ... do something ... } )
- However, this seems to defeat the purpose of the table design, as a change in the office name will break the authorization.
2) Use the officeid as the identifier to check for (e.g. if($officeid === 1) { ... do something ... } )
- However, this seems to lack maintainability, as developers constantly will have to reference the database to see what id refers to which office when they are editing current code or writing future code.
3) Define constants in a config file such that PRESIDENT_CONSTANT = 1, or something of the like, and check against the constant (e.g. if($officeid === PRESIDENT_CONSTANT) { ... do something ... } )
- However a) this shares issues with (1) in that the name of the position might change b) this is essentially recreating the officeid_officename table in the config file
Out of the three options, I feel like number two is the most correct, but I have lingering feelings concerning the maintainability issues. Is there a better way to accomplish what I need to do here?
Thanks.
Yes, #2 is correct.
I’m not really sure why you are concerned that you “constantly will have to reference the database.”
Assuming you are writing a classical PHP web app, each page load executes your script from the beginning. If you check the office at the beginning and store the result you can get away with a single query per page load. And in any event, databases are highly optimized for queries – doing a few of them isn’t going to hurt you.
The only downside to the above model is that you have a potential race condition: if the database changes during a single execution then you have a form of a privilege escalation vulnerability.
To address this, one approach is to authenticate (i.e. check the office) through the database at the beginning, cache the result, then run your code and queue up any database work inside an SQL transaction. Then re-authenticate before sending the page to the user. If the authentication fails, you send the user an error and roll back the transaction. If it succeeds (i.e. the office matches the cached result), send the user the page contents and commit the transaction.
This might be a lot to think about if you aren’t a professional web developer, but software (even for college organizations) has a way of getting used in unintended places, so best to consider the security ramifications before you start writing.