HACKS (with comments in code)

from werkzeug.security import generate_password_hash, check_password_hash
from datetime import date
import json

# Define a User Class/Template
# -- A User represents the data we want to manage
class User:    
    # constructor of a User object, initializes the instance variables within object (self)
    def __init__(self, name, uid, password, classOf, dob, age): # name, uid, and password are presets for each user
        self._name = name    # variables with self prefix become part of the object, 
        self._uid = uid
        self.set_password(password)
        self._dob = dob
        self._age = age
        self._classOf = classOf

    # use getter to get information from the defined objects
    @property
    def name(self):
        return self._name
    
    # use setter to update name after we create the object
    @name.setter
    def name(self, name):
        self._name = name
    
    # getter, gets the email id from object
    @property
    def uid(self):
        return self._uid
    
    # a setter function, allows name to be updated after initial object creation
    @uid.setter
    def uid(self, uid):
        self._uid = uid
        
    # check if uid parameter matches user id in object, return boolean
    def is_uid(self, uid):
        return self._uid == uid
    
    @property
    def password(self):
        return self._password[0:10] + "..." # because of security only show 1st characters

    # update password, this is conventional setter
    def set_password(self, password):
        """Create a hashed password."""
        self._password = generate_password_hash(password, method='sha512')

    # check password parameter versus stored/encrypted password
    def is_password(self, password):
        """Check against hashed password."""
        result = check_password_hash(self._password, password)
        return result
    
    @property 
    def classOf(self):
        return self._classOf

    @classOf.setter
    def classOf(self, classOf):
        self._classOf = classOf

    
    # output content using str(object) in human readable form, uses getter
    def __str__(self):
        return f'name: "{self.name}", id: "{self.uid}", psw: "{self.password}", classOf: "{self.classOf}", dob: "{self.dob}", age: "{self.age}"'

    # output command to recreate the object, uses attribute directly
    def __repr__(self):
        return f'Person(name={self._name}, uid={self._uid}, password={self._password}, classOf={self._classOf}, dob={self.dob}, age={self._age})'

 # a name getter method, extracts date of birth from object
    @property
    def dob(self):
        return self._dob
    
    # a setter function, allows date of birth to be updated after initial object creation
    @dob.setter
    def dob(self, dob):
        self._dob = dob

    @property 
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

def tester(users, uid, psw, classOf, dob, age):
    result = None
    for user in users:
        
        if user.uid == uid and user.is_password(psw):  # check for match
            print("* ", end="")
            result = user
        # print using __str__ method
        print(str(user))
    return result

from datetime import date

def calculate_age(born):
    today = date.today()
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day)) 


if __name__ == "__main__": #

    # defining each user as an object
    u1 = User(name='Vardaan Sinha', uid='vardaansinha', password='vardsin123!', classOf=2024, dob=[2006, 9, 28], age= calculate_age(date(2006, 9, 28)))
    u2 = User(name='Aarav Arora', uid='aaravarora09', password='aa09123!', classOf=2024, dob=[2005, 12, 14], age= calculate_age(date(2005, 12, 14)))
    u3 = User(name='Eshan Sinha', uid='esinha22', password='eshans22!', classOf=2019, dob=[2001, 3, 22], age= calculate_age(date(2001, 3, 22)))
    u4 = User(name='Mihir Sampath', uid='msampath', password='123coco', classOf=2023, dob=[2005, 6, 9], age= calculate_age(date(2005, 6, 9)))

    # list defining. VERY important part of CPT rubric!!
    users = [u1, u2, u3, u4]

    # Dictionary
    ''' 
    The __dict__ in Python represents a dictionary or any mapping object that is used to store the attributes of the object. 
    Every object in Python has an attribute that is denoted by __dict__. 
    Use the json.dumps() method to convert the list of Users to a JSON string.
    '''
    print("Dictionary: ")
    json_string = json.dumps([user.__dict__ for user in users]) 
    print(json_string)
Dictionary: 
[{"_name": "Vardaan Sinha", "_uid": "vardaansinha", "_password": "sha512$mJ5EjyDwoYLQZ0v9$9a72cf42677cfaa18ab1e2250f6291c520c631b6d8400e5c65406d72a5fedd54d36268c077f7ca62292174ab0bbc8ab5d77b44a8298f6ea22a7a23b29bb75684", "_dob": [2006, 9, 28], "_age": 16, "_classOf": 2024}, {"_name": "Aarav Arora", "_uid": "aaravarora09", "_password": "sha512$hLP6mSnrK4CDv5iY$65868cc23e04f34c49a16277301148ac4e980913779fa0aaccfeb21361b68aa36d9faade73778cba61751312706e456c172c9b7a5b2f7931f6c2c9b23813dfa9", "_dob": [2005, 12, 14], "_age": 17, "_classOf": 2024}, {"_name": "Eshan Sinha", "_uid": "esinha22", "_password": "sha512$5yOiQlrPBRFpCalS$3e3f4b4f236877c29be1b0359fffafaaced2e49cda08635385e9366467affe73ca98538eaf0f03b7651a741d156df6e16f8670761c03efa107da20e715c82ac9", "_dob": [2001, 3, 22], "_age": 21, "_classOf": 2019}, {"_name": "Mihir Sampath", "_uid": "msampath", "_password": "sha512$6xqjxn46k4kOay0f$4b9b111c8f8e816d93054dd4eeda2b2c93cd9924ff925820fe38aabeb8e39322221d142ce09751a027bf72c457455e8ed7e67cd1ca4d176199aa3576bc267299", "_dob": [2005, 6, 9], "_age": 17, "_classOf": 2023}]

Start Code for Hacks

from datetime import date

def calculate_age(born):
    today = date.today()
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day))

dob = date(2006, 9, 28)
age = calculate_age(date(2006, 9, 28))
print(age)
16

For an interesting change from the original code snippet for the hacks, I changed the password encoding for each of the users from sha256 to sha512. sha512 is a slightly faster cipher and adds a touch more security to the concealment of each of the user objects' passwords.