--- tags: Labs-F20, 2020 title: Lab 02 (Advanced) --- # Lab 2: Access Control These exercises are designed for students who are already comfortable with nested `if` expressions. Our goal is to have you look at how nested `if` expressions might get used for a specific problem in designing computing systems, and how we design and test such uses well. ## Problem 1 - `allow1` ### Instructions Consider this function: ``` fun allow1(who :: String, how :: String, what :: String) -> Boolean: doc: "check whether who is allowed to access what for purpose how" if (what == "gradebook"): if (who == "faculty") or (who == "ta"): if ((how == "write") == true): true else if (how == "read"): who == "faculty" else: false end else: false end else if (who == "faculty") or (who == "ta"): if (how == "write"): true else: true end else: if (how == "read") or (what == "jamboard"): true else: false end end end ``` Feel free to copy it into [CPO](https://code.pyret.org/editor) to get a better look at it. First off, just look at the code as a piece of written expression. What's your initial reaction? Does this seem like well-written code? Poorly written code? What are you focusing on as you make your initial assessment? Once you've collected your thoughts on this snippet of code and talked to your partner about it, write down your answers to the questions posed above in a shared Google Doc with your partner. ___ ### CHECKPOINT: **Call a TA over to discuss the questions above!** ___ ## Problem 2 - `show-gradebook` The `if-else` expression within `allow1` introduced in Problem 1 is meant to control access to materials in a course directory. The idea is that someone could call this function to check whether a requested access is allowed before performing a particular action. Many systems have such "access-control policies": social media sites restrict certain material to friends, Brown restricts access to your personal information to certain staff, and so on. For example, assume you are writing a web application for running courses, which has a function to display the contents of the gradebook. Your code might look like: ``` GRADEBOOK = "Mariana: A; Daryll: A; Chen: B+" fun show-gradebook(who :: String) --> String: doc: "display gradebook if who has access" if allow1(who, "read", "gradebook"): GRADEBOOK else: "Sorry, can't show the gradebook" end where: show-gradebook("student") is "Sorry, can't show the gradebook" show-gradebook("faculty") is GRADEBOOK end ``` 1. Under the policy captured by `allow1`, who can access what resources in what ways? Summarize your policy two ways: once in prose and once as a collection of test cases (in a `check:` block). 2. Think about different potential uses of a policy: what uses can you think of, which form (prose, code, tests) aligns well with each use? ___ ### CHECKPOINT: **Call a TA over once you and your partner have summarized your policy as prose and as a collection of test cases in your shared Google Doc.** ___ ## Problem 2.1 - `show-gradebook2` The `allow1` function seems awfully complex for guarding the gradebook. Couldn't we just write `show-gradebook` from Problem 2 as follows? ``` fun show-gradebook2(who :: String): doc: "Show the gradebook contents if permitted" if who == "faculty": GRADEBOOK else: "Sorry, can't show the gradebook" end end ``` Summarize the tradeoffs between the two versions (`show-gradebook` using the `allow1` function, and `show-gradebook2` as written above). --- ### CHECKPOINT: **After you and your partner have identified tradeoffs between `show-gradebook` and `show-gradebook2`, call over a TA to discuss.** --- ## Problem 3 - Redundant Boolean Logic One thing you may have noticed when assessing `allow1` is something we call **redundant boolean logic**. Simply put, redundant boolean logic is when `if` expressions can be simplified by removing specific references to `true` and `false`. :::info ### Basic redundant boolean logic examples: #### Example 1 Consider the following `if` expression: ``` if (is-rainy == true): "It's raining!" else: "It's not raining." end ``` Since `is-rainy` is a `Boolean`, it can either be `true` or `false`. Consider what the expression `is-rainy == true` will evaluate to for both values that `is-rainy` can take: ``` >> is-rainy = true >> is-rainy == true true ``` ``` >> is-rainy = false >> is-rainy == true false ``` As you can see, `is-rainy == true` will always evaluate to the value of `is-rainy`. Therefore, the `if` expression can be written as: ``` if (is-rainy): "It's raining!" else: "It's not raining." end ``` #### Example 2 Consider the following function: ``` fun is-precipitating(num-inches :: Number) --> Boolean: if (num-inches > 0): true else: false end end ``` Since the expression `num-inches > 0` will evaluate to a `Boolean`, it can either be `true` or `false`. If it is `true`, then we have an expression equivalent to ``` if (true): true # true is returned else: false end ``` If it is false, the expression is equivalent to ``` if (false): true else: false # false is returned end ``` As you can see, the value that the expression `num-inches > 0` evaluates to is always returned. Therefore, the `if` expression can be written as: ``` fun is-precipitating(num-inches :: Number) --> Boolean: num-inches > 0 end ``` ::: Now that we're a little bit more familiar with redundant boolean logic, let's see if you can fix it. Make a copy of `allow1` called `allow1b`, and modify this new function to eliminate any redundant boolean logic. To make sure that your modifications in `allow1b` don't interfere with the original functionality of `allow1`, write tests to see that the two functions return the same results. ___ ### CHECKPOINT: **Call a TA over when you think you've finished.** ***HINT:*** There are 3 specific instances of redundant boolean logic that we're looking for. ___ ## Problem 3.1 - `allow2`: Changing the Policy As `allow1` (the policy) is currently written, TAs are allowed to write lecture notes. Create a copy of `allow1` called `allow2`, and edit `allow2` to disallow TAs from writing lecture notes. What tests should you run against `allow2` to check that you made the edit correctly? --- ### CHECKPOINT: **Call a TA over once you've finished.** --- ## Problem 4 - If-Else Expression Guidelines Based on the previous two exercises, what would you propose as a set of guidelines for writing readable and maintainable `if-else` expressions similar to what is here? ## Problem 4.1 - `allow3` Rewrite the policy following your guidelines, calling it `allow3`. Compare and contrast your guidelines and revised code with that of another student or team. --- ### CHECKPOINT: **Call a TA over once you've written `allow3` according to your guidelines. Be ready to disuss your guidelines and the changes you made, as well as how your guidelines and changes were different than that of other students.** --- ## Problem 5 - Expressing an Access-control Policy Discuss the following questions with your partner: - What are the strengths and weaknesses of expressing an access-control policy in the manner of the original `if-else` expression? - What alternative might there be to writing an access-control policy as an `if-else` expression? How might those alternatives affect the tests? ## Problem 6 - Access-control as a Table What if we wanted to write our access-control policy using a table? Add these lines to the top of your code: ``` include tables include shared-gdrive("cs111-2020.arr", "1imMXJxpNWFCUaawtzIJzPhbDuaLHtuDX") ``` As an example of how we can create a table in Pyret, here is a table containing a couple of rows of Rhode Island municipality data: ``` municipalities = table: name, city, population-2000, population-2010 row: "Providence", true, 173618, 178042 row: "Cranston", true, 79269, 80387 end ``` Your tasks for this problem: - Create a table named `access-control` where you can store all of the data about the access privileges for each user category ("faculty", "ta", "student"). - Rewrite the policy you've written in `allow3` in a new function named `allow4`, which uses the `access-control` table. - Compare the two ideas here, or putting policies in if-expressions versus putting them in tables. What are the advantages and disadvantages of each? ***HINT:*** How could the `filter-by` function help you? ([documentation here](https://hackmd.io/@cs111/table)) --- ### CHECKPOINT: **Call a TA over once you've written `allow4`, the policy using a table.** --- ## Final Reflection Step back and think about the work you did in this lab. Did you encounter any new ideas about CS today? Did this lab emphasize anything that hadn't been stressed in your previous CS courses? What are you taking away from this lab?