class MuscleModel(db.Model): __tablename__ = "MuscleIndex" id = db.Column(db.Integer, primary_key=True) # Optional: ID of this muscle used to locate on the anatomy chart diagram_id = db.Column(db.Integer, nullable=True) # Canonical name used when exporting and importing/linking data. canonical_name = db.Column(db.String(100), unique=True, nullable=False) # Long, anatomical name for this muscle name = db.Column(db.String(100), unique=True, nullable=False) # Shortened name for this muscle. Used for display. short_name = db.Column(db.String(50), nullable=True) # List of groups this muscle belongs to groups = db.relationship("MuscleGroupModel", secondary="MuscleGroupAssociation", back_populates="muscles") @staticmethod def has_owner(): return False def __str__(self): return "%i MuscleModel: %s" % (self.id, self.name)
class UnitModel(db.Model): __tablename__ = "UnitIndex" id = db.Column(db.Integer, primary_key=True) # canonical name, used for linking and export. Example: "meters" canonical_name = db.Column(db.String(40), unique=True, nullable=False) # Long name, plural form of this unit. Example: "meters" name = db.Column(db.String(40), unique=True, nullable=False) # Short form of this unit. Example: "m" abbreviation = db.Column(db.String(20), nullable=False) # What does this unit measure? Example: "length" dimension = db.Column(db.String(20), nullable=False) # What do we multiply this unit by to get the base unit for the dimension? # Example: The "length" dimension's base unit is centimeters, there are # 100cm in 1m, so for the meters unit this would be set to 100 multiplier = db.Column(db.Float(decimal_return_scale=4), nullable=False, default=1.0) # Can this unit be deleted? (Basically, is this a user defined unit or a pre-packaged unit?) # Example: Because the meters unit comes as a default unit in Variance, # this would be set to False. removable = db.Column(db.Boolean, default=True) @staticmethod def has_owner(): return False @staticmethod def get_id_by_name(text): name_match = UnitModel.query.filter_by(name=text).first() if name_match: return name_match.id @staticmethod def get_id_by_abbreviation(text): abbreviation_match = UnitModel.query.filter_by( abbreviation=text).first() if abbreviation_match: return abbreviation_match.id def __str__(self): return "UnitModel (%i): %s (%s) %s, removable(%s), mult(%s) " % (int( self.id), self.name, self.abbreviation, self.dimension, str(self.removable), str(self.multiplier)) def __int__(self): return int(self.multiplier) def __float__(self): return float(self.multiplier)
class LambdaModel(db.Model): __tablename__ = "LambdaIndex" id = db.Column(db.Integer, primary_key=True) # Name of this lambda function, for example: "Percentage of 1 Rep Max" name = db.Column(db.String(100), nullable=False) # Callable/internal name of this lambda function, for example "percent_1rm" function_name = db.Column(db.String(40), nullable=False) def __str__(self): return "LambdaModel (%i): %s - %s" % (self.id, self.name, self.function_name)
class MealPlanModel(db.Model): __tablename__ = "MealPlanIndex" id = db.Column(db.Integer, primary_key=True) # Management Info # Name of this meal plan name = db.Column(db.String(60), unique=True, nullable=False) description = db.Column(db.Text, nullable=True) # If set to true, all users can see this ingredient is_public = db.Column(db.Boolean, nullable=False, default=False) # The user who added this mealplan to the database owner_id = db.Column(db.Integer, db.ForeignKey( "UserIndex.id"), nullable=False) owner = db.relationship("UserModel", back_populates="mealplans") days = db.relationship("MealPlanDayModel", back_populates="mealplan") @staticmethod def has_owner(): return True def check_owner(self, id): return self.owner_id == id
class ExerciseModel(db.Model): __tablename__ = "ExerciseIndex" id = db.Column(db.Integer, primary_key=True) # Internal name of the exercise for linking + id canonical_name = db.Column(db.String(100), unique=True, nullable=False) # Name of the exercise to display to the user name = db.Column(db.String(100), unique=True, nullable=False) description = db.Column(db.Text, nullable=True) # Is this exercise measured in time? use_duration = db.Column(db.Boolean, nullable=False, default=0) # Is this exercise measured in distance? use_distance = db.Column(db.Boolean, nullable=False, default=0) # Is this exercise measured in weight? use_weight = db.Column(db.Boolean, nullable=False, default=0) # What pieces of equipment does this exercise use? equipment = db.relationship("EquipmentModel", secondary="ExerciseEquipmentList", back_populates="exercises") # Is this exercise a variation of another exercise, if so, which exercise? # (Ex: Close grip bench is a variation of bench press) parent_exercise_id = db.Column(db.Integer, db.ForeignKey("ExerciseIndex.id"), nullable=True) parent_exercise = db.relationship( "ExerciseModel", foreign_keys="ExerciseModel.parent_exercise_id", back_populates="variations") variations = db.relationship("ExerciseModel") def __str__(self): return "%u Exercise: %s dur(%s), dis(%s), wght(%s), equip(%s)" % ( self.id, self.name, str(self.use_duration), str(self.use_distance), str(self.use_weight), str(self.equipment.name)) @staticmethod def has_owner(): return False
class EquipmentModel(db.Model): __tablename__ = "EquipmentIndex" id = db.Column(db.Integer, primary_key=True) # Name of this piece of equipment. Example: "example-equipment" canonical_name = db.Column(db.String(40), unique=True, nullable=False) # Name of this piece of equipment. Example: "Dumbbells" name = db.Column(db.String(40), unique=True, nullable=False) # Describe this piece of equipment. description = db.Column(db.String(20), nullable=True) # List of exercises that use this piece of equipment. exercises = db.relationship( "ExerciseModel", secondary="ExerciseEquipmentList", back_populates="equipment")
class GymModel(db.Model): __tablename__ = "GymIndex" """ Every Gym can have multiple pieces of equipment associated with it. Gyms can be public or private (private by default). Gyms are really nothing more than a collection of equipment, making it easier to plan workouts """ id = db.Column(db.Integer, primary_key=True) # Name of the gym name = db.Column(db.String(100), unique=False, nullable=False) # Location of the gym location = db.Column(db.String(100), nullable=True) description = db.Column(db.Text, nullable=True) ### Ownership and visibility # Is this gym visible to all users? If set to true, then all users can use # this gym is_public = db.Column(db.Boolean, nullable=False, default=False) # The user who added this gym to the database owner_id = db.Column(db.Integer, db.ForeignKey( "UserIndex.id"), nullable=False) owner = db.relationship("UserModel", backref="gyms") equipment = db.relationship("EquipmentModel", secondary="GymEquipmentList") @staticmethod def has_owner(): return True def check_owner(self, id): return self.owner.id == id def __str__(self): return "%u Gym: %s public(%s), owned by %u (%s)" % ( self.id, self.name, str(self.is_public), self.owner.id, self.owner.username)
class MuscleGroupModel(db.Model): __tablename__ = "MuscleGroupIndex" id = db.Column(db.Integer, primary_key=True) canonical_name = db.Column(db.String(100), unique=True, nullable=False) # Display name of this muscle group name = db.Column(db.String(100), unique=True, nullable=False) description = db.Column(db.Text, nullable=True) # List of muscles in this muscle group muscles = db.relationship("MuscleModel", secondary="MuscleGroupAssociation", back_populates="groups") @staticmethod def has_owner(): return False def __str__(self): return "%u MuscleGroupModel: %s" % (self.id, self.name)
class WorkoutProgramModel(db.Model): __tablename__ = "WorkoutProgramIndex" id = db.Column(db.Integer, primary_key=True) # Name of the workout program name = db.Column(db.String(100), nullable=False) # Description of the workout program description = db.Column(db.String(300), nullable=True) # Can other users see this workout program? is_public = db.Column(db.Boolean, nullable=False, default=False) # User who owns this program owner_id = db.Column(db.Integer, db.ForeignKey("UserIndex.id"), nullable=False) owner = db.relationship("UserModel", back_populates="programs") # Workouts in this program workouts = db.relationship("WorkoutModel", back_populates="program", cascade="all, delete") @staticmethod def has_owner(self): return True # Returns True is the given user id is considered the owner of this # tracker entry def check_owner(self, id): return self.owner_id == id def __str__(self): return "%u ProgramModel: %s, %u(%s), public(%s)" % ( self.id, self.name, self.owner_id, self.owner.username, str(self.is_public))
class WorkoutModel(db.Model): __tablename__ = "WorkoutIndex" id = db.Column(db.Integer, primary_key=True) # Name of the workout day name = db.Column(db.String(100), nullable=False) # What day does this occur on? Freeform entry day = db.Column(db.String(20), nullable=True) # What week does this occur on? Freeform entry week = db.Column(db.String(20), nullable=True) # Sets of exercises that are performed on this day sets = db.relationship("SetPlanModel", back_populates="workout", cascade="all, delete") # Workout Program this workout belongs to parent_program_id = db.Column(db.Integer, db.ForeignKey("WorkoutProgramIndex.id"), nullable=False) program = db.relationship("WorkoutProgramModel", back_populates="workouts") @staticmethod def has_owner(self): return True # Returns True is the given user id is considered the owner of this # tracker entry def check_owner(self, id): return self.program.check_owner(id) def __str__(self): return "%u WorkoutModel: %s on %s, %u" % (self.id, self.name, self.day, self.week_id)
class TrackerModel(db.Model): __tablename__ = "TrackerIndex" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(40), nullable=False) dimension = db.Column(db.String(20), nullable=False) owner_id = db.Column(db.Integer, db.ForeignKey("UserIndex.id"), nullable=False) owner = db.relationship("UserModel", back_populates="trackers") entries = db.relationship("TrackerEntryModel", back_populates="tracker") def __str__(self): return "%u Tracker: %s (%s), user %s (%u)" % (int( self.id), str(self.name), str( self.dimension), str(self.owner.username), int(self.owner_id)) @staticmethod def has_owner(self): return True def check_owner(self, id): return self.owner_id == id
class ConsumedEntryModel(db.Model): __tablename__ = "ConsumedEntryIndex" id = db.Column(db.Integer, primary_key=True) # Name of the food that was consumed. name = db.Column(db.String(60), nullable=False) # Time when this entry was made time = db.Column(db.DateTime(), nullable=False, default=datetime.now()) # The user who added this mealplan to the database owner_id = db.Column(db.Integer, db.ForeignKey( "UserIndex.id"), nullable=False) owner = db.relationship("UserModel", back_populates="consumption_entries") # Nutritional Info # Amount of calories consumed (grams) calories = db.Column(db.Float, nullable=False, default=0) # Amount of protein consumed (grams) protein = db.Column(db.Float, nullable=False, default=0) # Amount of carbohydrates consumed (grams) carbohydrates = db.Column(db.Float, nullable=False, default=0) # Amount of fats consumed (grams) fat = db.Column(db.Float, nullable=False, default=0) # Linking to a Consumable servings = db.Column(db.Float, nullable=False, default=1) consumable_id = db.Column(db.Integer, db.ForeignKey("ConsumableIndex.id")) consumable = db.relationship("ConsumableModel") @staticmethod def has_owner(): return True def check_owner(self, id): return self.owner_id == id def __str__(self): return "%u ConsumedEntryModel: %s @ %s, o(%u), c(%u)" % ( self.id, self.name, str(self.time), self.owner_id, self.consumable_id)
class MuscleSectionModel(db.Model): __tablename__ = "MuscleSectionIndex" id = db.Column(db.Integer, primary_key=True) # Optional: ID of this muscle section sused to locate on the anatomy chart diagram_id = db.Column(db.Integer, nullable=True) # Name of this muscle section. For example "Upper pec" name = db.Column(db.String(100), unique=True, nullable=False) # What muscle is this muscle section of? parent_muscle_id = db.Column(db.Integer, db.ForeignKey("MuscleIndex.id"), nullable=False) parent_muscle = db.relationship("MuscleModel", backref="sections") @staticmethod def has_owner(): return False def __str__(self): return "%i MuscleSectionModel: %s" % (self.id, self.name)
class PermissionModel(db.Model): __tablename__ = "PermissionIndex" id = db.Column(db.Integer, primary_key=True) # Action that is permitted. (Ex: tracker.entry.new) action = db.Column(db.String(100), nullable=False) # Allow all users with this role to perform this action. (Ex: admin) allow_role = db.Column(db.String(20), nullable=True) # Allow the given user ID to perform this action. allow_user = db.Column(db.Integer, db.ForeignKey( "UserIndex.id"), nullable=True) # If set to true, the perms will check to make sure that the action is being performed by the user that owns the given database row entry # Ownership is tracked by the "owner" property allow_owner = db.Column(db.Boolean, nullable=True) # If set to true, the perms will check to make sure that the action being performed is on a row that has is_public set to True # Example: Some Recipes can be public for everyone to view, others are # private check_public = db.Column(db.Boolean, nullable=True) # If set to true, this action can be performed by ANY client. # Example: Viewing the list of units # Usually just used for view actions force_public = db.Column(db.Boolean, nullable=True) # For debugging and CLI purposes def __str__(self): return "Perm ID %5i: %25s - r(%s), u(%s), o(%s), cp(%s), fp(%s)" % (int(self.id), str(self.action), str(self.allow_role), str(self.allow_user), str(self.allow_owner), str(self.check_public), str(self.force_public)) # Validation process: # Get all rows with the target action # For each row: If user fits into 1 row, then return True # If user does not fit into any rows, return False # Parameters: user - the UserModel of the user that is performing the action # model - the SQLAlchemyModel of what is being modified def check_user(self, user, model): if self.force_public is not None: return self.force_public if user: # If the client is not logged in, then it's ok to pass False instead of a UserModel if self.allow_user is not None: if self.allow_user == user.id: return True if self.allow_role is not None: if self.allow_role == user.role: return True if self.allow_owner is not None: # If the model is able to have an owner, then check if the owner matches the current user id if model: # If the model has not been loaded yet then we cannot check for an owner if model.has_owner() and model.check_owner(user.id): return True else: logging.warning("Attempted to check ownership of a model for perms rule " + str(self)) # TODO: Make a log somewhere to notify dev that we attempted to # check owner of a None model if self.check_public is not None: if model: # If the model has not been loaded yet then we cannot check for an owner if model.is_public: return True # TODO: Make a log somewhere to notify dev that we attempted to # check owner of a None model return False
class UserModel(db.Model): __tablename__ = "UserIndex" id = db.Column(db.Integer, primary_key=True) # Management Info username = db.Column(db.String(30), unique=True, nullable=False) # Email address of the user. NOTE: Can be NULL! email = db.Column(db.String(80), nullable=True) # Password hash of the user. password = db.Column(db.String(128), nullable=False) # Date this user was born. Used for calculating age. birthdate = db.Column(db.Date(), nullable=False) # Datetime this user was created. created_on = db.Column(db.DateTime(), nullable=False, default=datetime.now()) # User role. Current values: "user", "admin" role = db.Column(db.String(10), nullable=False, default="user") # User Data # List of trackers this user has running trackers = db.relationship( "TrackerModel", back_populates="owner", cascade="all, delete") # List of nutritional items created by this user consumables = db.relationship( "ConsumableModel", back_populates="owner", cascade="all, delete") recipies = db.relationship( "RecipeModel", back_populates="owner", cascade="all, delete") mealplans = db.relationship( "MealPlanModel", back_populates="owner", cascade="all, delete") set_entries = db.relationship( "SetEntryModel", back_populates="owner", cascade="all, delete") consumption_entries = db.relationship( "ConsumedEntryModel", back_populates="owner", cascade="all, delete") programs = db.relationship( "WorkoutProgramModel", back_populates="owner", cascade="all, delete") # Unit Display Preferences # lb or kg exercise_weight_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) exercise_weight_unit = db.relationship( "UnitModel", foreign_keys="UserModel.exercise_weight_unit_id") # mile or km exercise_distance_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) exercise_distance_unit = db.relationship( "UnitModel", foreign_keys="UserModel.exercise_distance_unit_id") # oz/lb or grams food_weight_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) food_weight_unit = db.relationship( "UnitModel", foreign_keys="UserModel.food_weight_unit_id") # fl. oz or Liters food_volume_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) food_volume_unit = db.relationship( "UnitModel", foreign_keys="UserModel.food_volume_unit_id") # Pounds, stone, or kg? body_weight_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) body_weight_unit = db.relationship( "UnitModel", foreign_keys="UserModel.body_weight_unit_id") # Feet or meters? body_distance_large_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) body_distance_large_unit = db.relationship( "UnitModel", foreign_keys="UserModel.body_distance_large_unit_id") # Inches or cm? body_distance_small_unit_id = db.Column( db.Integer, db.ForeignKey("UnitIndex.id"), nullable=False) body_distance_small_unit = db.relationship( "UnitModel", foreign_keys="UserModel.body_distance_small_unit_id") # Diet Settings # Can this user not eat peanuts? (setting to True means that no recipies # containing peanuts will be suggested) no_peanuts = db.Column(db.Boolean, nullable=True) # Can this user not eat treenuts? no_treenuts = db.Column(db.Boolean, nullable=True) # Can this user not eat dairy? no_dairy = db.Column(db.Boolean, nullable=True) # Can this user not eat eggs? no_eggs = db.Column(db.Boolean, nullable=True) # Can this user not eat pork? no_pork = db.Column(db.Boolean, nullable=True) # Can this user not eat beef (cow)? no_beef = db.Column(db.Boolean, nullable=True) # Can this user not eat meat? no_meat = db.Column(db.Boolean, nullable=True) # Can this user not eat fish? no_fish = db.Column(db.Boolean, nullable=True) # Can this user not eat shellfish? no_shellfish = db.Column(db.Boolean, nullable=True) # Can this user not eat gluten? no_gluten = db.Column(db.Boolean, nullable=True) # Does this user require vegetarian only foods? is_vegetarian = db.Column(db.Boolean, nullable=True) # Does this user require vegan only foods? is_vegan = db.Column(db.Boolean, nullable=True) # Does this user require kosher only foods? is_kosher = db.Column(db.Boolean, nullable=True) # Returns the age (in years) of this user. Integer, not a fraction def age(self): bday = datetime.date(self.birthdate) today = date.today() return today.year - bday.year - \ ((today.month, today.day) < (bday.month, bday.day)) def get_tags(self): tags = [] if self.no_pork: tags.append("nopork") if self.no_meat: tags.append("nomeat") if self.no_fish: tags.append("nofish") if self.no_shellfish: tags.append("noshellfish") if self.no_beef: tags.append("nobeef") if self.no_dairy: tags.append("nodairy") if self.no_eggs: tags.append("noeggs") if self.no_peanuts: tags.append("nopeanuts") if self.no_gluten: tags.append("nogluten") if self.no_treenuts: tags.append("notreenuts") if self.is_vegan: tags.append("vegan") if self.is_vegetarian: tags.append("vegetarian") if self.is_kosher: tags.append("kosher") return tags def set_password(self, password): self.password = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password, password) @staticmethod def has_owner(self): return False