Try   HackMD

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 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.

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)


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?