Skip to content

Instantly share code, notes, and snippets.

@ahussain3
Last active September 1, 2019 22:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahussain3/f31db43f84a523ca7d6292eb3e437d9b to your computer and use it in GitHub Desktop.
Save ahussain3/f31db43f84a523ca7d6292eb3e437d9b to your computer and use it in GitHub Desktop.
Todo list design exercise (Advanced Software Design Week 2)
from enum import Enum
from models import Base
from datetime import DateTime
# CONSTANTS
DEFAULT_PRIORITY = 0
# MODELS
class ItemState(Enum):
PENDING = "PENDING"
IN_PROGRESS = "IN_PROGRESS"
UNDER_REVIEW = "UNDER_REVIEW"
BLOCKED = "BLOCKED"
COMPLETED = "COMPLETED"
class RelationshipType(Enum):
FRIEND = "FRIEND"
class VisibilityLevel(Enum):
FRIENDS = "FRIENDS" # viewable by friends of the authed user
PRIVATE = "PRIVATE" # viewable by authed user only
alias itemId: int ## autogenerated
class Item(Base):
item_id: itemId ## int autogenerated
list_id: foreignKey(List, backref="items", list=True) # many-to-one relationship
title: String
description: Optional[String]
when_created: DateTime
when_updated: Optional[DateTime]
when_completed: Optional[DateTime]
when_deleted: Optional[DateTime]
when_due: Optional[DateTime]
state: Enum(ItemState)
is_active: bool # inactive items are considered deleted/archived
priority: int # (check constraint, 0 <= priority <= 5)
visibility: Enum(VisibilityLevel)
class List(Base):
list_id: int # autogenerated
name: str
when_created: DateTime
class User(Base):
user_id: int # autogenerated
list_id: foreignKey(TodoList, backref="user", list=False)
@property
def friends(self) -> List[User]:
return [friendship.to for friendship in db.get(
Relationship, type=RelationshipType.FRIEND, from=self
)]
class Relationship(Base):
"""To create a bidirectional relationship, you need one relationship going in each direction."""
type: Enum(RelationshipType)
from: foreignKey(User)
to: foreignKey(User)
class TimePeriod:
from: Optional[DateTime]
to: Optional[DateTime]
# LOGIC
def get_items_for_user(
user_id: int,
when_created: Optional[TimePeriod] = None,
when_due: Optional[TimePeriod] = None,
state: Optional[List[ItemState]] = None,
visibility: VisibilityLevel = VisibilityLevel.FRIENDS,
limit = Optional[int] = None,
) -> List[Item]:
def create_item(
title: str,
description: Optional[str] = None,
status: Optional[] = None,
priority: Optional[int] = None,
when_due: Optional[DateTime] = None,
visibility: VisibilityLevel = VisibilityLevel.FRIENDS,
) -> Item:
def edit_item(
item_id: itemId,
title: Optional[str] = None,
description: Optional[str] = None,
status: Optional[] = None,
priority: Optional[int] = None,
when_due: Optional[DateTime] = None,
visibility: VisibilityLevel = VisibilityLevel.FRIENDS,
) -> Item:
"""Any field that is None is left untouched."""
def delete_item(item_id: itemId) -> None:
# API methods
def login() -> SessionId:
# set `logged_in_user` on Session
def logout() -> None:
# need some kind of middleware such that each function below knows who the logged in
# user is.
def get_friends() -> List[User]:
"""Get a list of friends for the logged in user."""
def view_list(
user_id: Optional[int] = None, # None means show list for logged in user
n: int = 50,
show_completed: bool = true,
order_by: str = "when_created", # one of "priority" | "when_created" | "when_due"
for_user: Optional[int(userId)], # if none it shows the list of the authenticated user
) -> List[Item]:
"""By default shows the n most recent todo items."""
# This function needs to check to see who the authenticated user is and check
# that they have permission to view the content they are trying to view?
def create_item(
title: str,
description: Optional[str] = None,
) -> Item:
# Check that the logged in user has permission to perform this action
def set_status(item_id: itemId, status: str) -> Item:
# Check that the logged in user has permission to perform this action
def set_priority(item_id: itemId, priority: int) -> Item:
# Check that the logged in user has permission to perform this action
def set_due_date(item_id: itemId, due_date: DateTime) -> Item:
# Check that the logged in user has permission to perform this action
def set_visiblity(item_id: itemId, is_private: bool) -> Item:
# Check that the logged in user has permission to perform this action
def delete_item(item_id: itemId) -> None:
# Check that the logged in user has permission to perform this action
def mark_as_done(item_id: itemId) -> Item:
# Check that the logged in user has permission to perform this action
def make_as_not_done(item_id: itemId) -> Item:
# Check that the logged in user has permission to perform this action
# UI
# I think the most important thing here is that the authentication / authorization
# logic is kept separate from the main API.
# The UI for viewing a friends todo list would be the same as viewing one's own todo
# list, except that the view_list() API call is made by passing in the user id of the
# friend whose list you want to view.
# There needs to be a separate UI page where the user can view a list of their friends,
# and then they need to select a friend in order to view their todo list.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment