Skip to content

Commit

Permalink
WIP. Improved many views. Refactored database schema.
Browse files Browse the repository at this point in the history
  • Loading branch information
TaaviE committed Nov 29, 2019
1 parent c250ca5 commit dce26f1
Show file tree
Hide file tree
Showing 33 changed files with 534 additions and 381 deletions.
6 changes: 6 additions & 0 deletions example_config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# coding=utf-8
"""
This file should contain the app's configuration, make sure to fill out everything
"""
import logging
import subprocess


class Config(object):
"""
Contains everything required for configuring the application
"""
ENV = "debug" # TODO: Replace with "production"
FLASK_DEBUG = True # TODO: Disable in production
DEVELOPMENT = True # TODO: Disable in production
Expand Down
5 changes: 4 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ def use_identity(element, compiler, **kw):
release=Config.CURRENT_GIT_SHA)

from models.users_model import User, Role

from flask_security import SQLAlchemyUserDatastore, Security

user_datastore = SQLAlchemyUserDatastore(db, User, Role)

security = Security(app,
Expand All @@ -78,6 +78,9 @@ def use_identity(element, compiler, **kw):
send_confirmation_form=ExtendedConfirmationForm,
forgot_password_form=ExtendedForgotPasswordForm)

# noinspection PyUnresolvedReferences
from models.enums import event_type_to_id, subscription_type_to_id, audit_event_type_to_id, wishlist_status_to_id

from views import static, login, views, user_specific, edit, test

app.register_blueprint(edit)
Expand Down
1 change: 1 addition & 0 deletions models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""
Contains all the models used in SecretSantaGraph
"""
import models.enums
import models.family_model
import models.names_model
import models.shuffles_model
Expand Down
18 changes: 1 addition & 17 deletions models/audit_events_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,14 @@
from models.family_model import Group


class AuditEventType(db.Model):
"""
Specifies how event types are stored in the database
"""
__tablename__ = "audit_events_types"

id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
name: str = Column(VARCHAR(), nullable=False)
description: str = Column(VARCHAR(1024), nullable=False)


audit_event_type_to_id: dict = {}
for event_type in AuditEventType.query.all():
audit_event_type_to_id[event_type.name.lower().replace(" ", "_")] = event_type.id


class AuditEvent(db.Model):
"""
Specifies how audit events are stored in the database
"""

__tablename__ = "audit_events"

event_type_id: int = Column(Integer(), ForeignKey(AuditEventType.id), nullable=False)
event_type_id: int = Column(Integer(), ForeignKey("event_types.id"), nullable=False)
when: datetime = Column(TIMESTAMP(), server_default=FetchedValue(), nullable=False)
id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
event_at: datetime = Column(TIMESTAMP(), nullable=True)
Expand Down
71 changes: 71 additions & 0 deletions models/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# coding=utf-8
"""
Initializes a few lookup tables for quick name to ID
"""
from sqlalchemy import BigInteger, Column, FetchedValue, Integer, VARCHAR

from main import db


class AuditEventType(db.Model):
"""
Specifies how event types are stored in the database
"""
__tablename__ = "audit_events_types"

id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
name: str = Column(VARCHAR(), nullable=False)
description: str = Column(VARCHAR(1024), nullable=False)


class ShufflingEventType(db.Model):
"""
Specifies how event types are stored in the database
"""

__tablename__ = "event_types"

id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
name: str = Column(VARCHAR(), nullable=True)


class SubscriptionType(db.Model):
"""
Specifies different types of subscriptions
"""
__tablename__ = "subscription_types"

id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
name: str = Column(VARCHAR(255), nullable=False)

def __repr__(self):
return "<id {}>".format(self.user_id)

def __str__(self):
return "{\"id\": {id}, \"name\": \"{name}\"}".format(id=self.id, name=self.name)


class WishlistStatusType(db.Model):
"""
Specifies the different states a note can be in
"""
__tablename__ = "wishlist_status_types"
id: int = Column(Integer(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
name: str = Column(VARCHAR(255), nullable=False)


event_type_to_id: dict = {}
for event_type in ShufflingEventType.query.all():
event_type_to_id[event_type.name.lower().replace(" ", "_")] = event_type.id

subscription_type_to_id: dict = {}
for subscription_type in SubscriptionType.query.all():
subscription_type_to_id[subscription_type.name.lower().replace(" ", "_")] = subscription_type.id

audit_event_type_to_id: dict = {}
for event_type in AuditEventType.query.all():
audit_event_type_to_id[event_type.name.lower().replace(" ", "_")] = event_type.id

wishlist_status_to_id = {}
for status in WishlistStatusType.query.all():
wishlist_status_to_id[status.name.lower().replace(" ", "_")] = status.id
45 changes: 14 additions & 31 deletions models/events_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,31 @@
from __future__ import annotations

from datetime import datetime
from typing import List

from sqlalchemy import BigInteger, Column, FetchedValue, ForeignKey, Integer, TIMESTAMP, VARCHAR
from sqlalchemy import BigInteger, Boolean, Column, FetchedValue, ForeignKey, Integer, TIMESTAMP, VARCHAR
from sqlalchemy.orm import relationship

from main import db
from models.family_model import Group


class ShufflingEventType(db.Model):
"""
Specifies how event types are stored in the database
"""

__tablename__ = "event_types"

id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
name: str = Column(VARCHAR(), nullable=True)


event_type_to_id: dict = {}
for event_type in ShufflingEventType.query.all():
event_type_to_id[event_type.name.lower().replace(" ", "_")] = event_type.id


class ShufflingEvent(db.Model):
"""
Specifies how events are stored in the database
"""

__tablename__ = "events"

id: int = Column(BigInteger(), server_default=FetchedValue(), primary_key=True, unique=True, nullable=False)
created_at: datetime = Column(TIMESTAMP(), server_default=FetchedValue(), nullable=False)
name: str = Column(VARCHAR(255), nullable=False)
event_at: datetime = Column(TIMESTAMP(), nullable=True)
group_id: int = Column(Integer(), ForeignKey(Group.id), nullable=False)
event_type: int = Column(Integer(), ForeignKey(ShufflingEventType.id), nullable=False)
event_type: int = Column(Integer(), ForeignKey("event_types.id"), nullable=False)

admins: List[User] = relationship("User",
secondary="events_admins",
backref="events_administered")

def __str__(self):
return "{" \
Expand All @@ -60,6 +49,9 @@ def __str__(self):
)

def as_dict(self):
"""
Returns a dictionary of the event with all relevant information
"""
return {
"id": self.id,
"created_at": self.created_at,
Expand All @@ -75,22 +67,13 @@ def __hash__(self):

class EventAdmin(db.Model):
"""
Specifies how event admin relationships are modeled in the database
@param user_id: user's ID
@param event_id: event_id where the family belongs ID
@param admin: if the user is the adming of the group
Specifies how user-event administration relationships are modeled in the database
"""
__tablename__ = "events_admins"
user_id: int = Column(Integer, ForeignKey("User.id"), primary_key=True, unique=True, nullable=False)
event_id: int = Column(Integer, ForeignKey("ShufflingEvent.id"), primary_key=True, nullable=False)
user_id: int = Column(Integer, ForeignKey("users.id"), primary_key=True, unique=True, nullable=False)
event_id: int = Column(Integer, ForeignKey("events.id"), primary_key=True, nullable=False)
admin: bool = Column(Boolean, nullable=False)
confirmed: bool = Column(Boolean, nullable=False, default=False)

def __init__(self, user_id: int, group_id: int, admin: bool):
self.user_id = user_id
self.group_id = group_id
self.admin = admin

def __repr__(self):
return "<user_id {}, group_id {}>".format(self.user_id, self.group_id)
89 changes: 48 additions & 41 deletions models/family_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ class Group(db.Model):
backref=backref("Group", lazy="dynamic")
)

admins: List[User] = relationship(
"User",
secondary="groups_admins",
backref="groups_administered"
)

events: List[ShufflingEvent] = relationship("ShufflingEvent")

def __init__(self, group_id: int, group_name: str):
self.id = group_id
self.name = group_name
Expand All @@ -40,37 +48,9 @@ def __repr__(self):
return "<id {}>".format(self.id)


class GroupAdmin(db.Model):
"""
Specifies how user-group-admin relationships are modeled in the database
@param user_id: user's ID
@param group_id: family_id where the family belongs ID
@param admin: if the user is the adming of the group
"""

__tablename__ = "groups_admins"
user_id: int = Column(Integer, ForeignKey("User.id"), primary_key=True, unique=True, nullable=False)
group_id: int = Column(Integer, ForeignKey("Group.id"), primary_key=True, nullable=False)
admin: bool = Column(Boolean, nullable=False)
confirmed: bool = Column(Boolean, nullable=False, default=False)

def __init__(self, user_id: int, group_id: int, admin: bool):
self.user_id = user_id
self.group_id = group_id
self.admin = admin

def __repr__(self):
return "<user_id {}, group_id {}>".format(self.user_id, self.group_id)


class Family(db.Model):
"""
Specifies how families are modeled in the database
@param family_id: family's ID
@param family_group: group where the family belongs ID
@param family_name: 255 letter name of the group
"""

__tablename__ = "families"
Expand All @@ -84,10 +64,16 @@ class Family(db.Model):
backref=backref("Family", lazy="dynamic")
)

def __init__(self, family_id, family_group, family_name):
self.id = family_id
self.group = family_group
self.name = family_name
members: List[User] = relationship(
"User",
secondary="users_families"
)

admins: List[User] = relationship(
"User",
secondary="families_admins",
backref=backref("User", lazy="dynamic")
)

def __repr__(self):
return "<id {}>".format(self.id)
Expand All @@ -96,21 +82,42 @@ def __repr__(self):
class FamilyGroup(db.Model):
"""
Specifies how family-group relationships are defined in the database
@param family_id: family's ID
@param group_id: ID of the group where the family belongs
@param confirmed: if the family has been authorized to be in the group
"""

__tablename__ = "families_groups"
family_id: int = Column(Integer, ForeignKey(Family.id), primary_key=True, unique=False, nullable=False)
group_id: int = Column(Integer, ForeignKey(Group.id), unique=False, nullable=False)
confirmed: bool = Column(Boolean, default=False, unique=False, nullable=False)

def __init__(self, family_id: int, group_id: int, confirmed: bool = False):
self.family_id = family_id
self.group_id = group_id
self.confirmed = confirmed
def __repr__(self):
return "<id {}>".format(self.family_id)


class FamilyAdmin(db.Model):
"""
Specifies how user-family administration relationships are modeled in the database
"""

__tablename__ = "families_admins"
user_id: int = Column(Integer, ForeignKey("users.id"), primary_key=True, nullable=False)
family_id: int = Column(Integer, ForeignKey(Family.id), primary_key=True, nullable=False)
admin: bool = Column(Boolean, nullable=False)
confirmed: bool = Column(Boolean, nullable=False, default=False)

def __repr__(self):
return "<user_id {}>".format(self.user_id)


class GroupAdmin(db.Model):
"""
Specifies how user-group-admin relationships are modeled in the database
"""

__tablename__ = "groups_admins"
user_id: int = Column(Integer, ForeignKey("users.id"), primary_key=True, unique=True, nullable=False)
group_id: int = Column(Integer, ForeignKey(Group.id), primary_key=True, nullable=False)
admin: bool = Column(Boolean, nullable=False)
confirmed: bool = Column(Boolean, nullable=False, default=False)

def __repr__(self):
return "<id {}>".format(self.family_id)
return "<user_id {}, group_id {}, admin {}>".format(self.user_id, self.group_id, self.admin)
7 changes: 0 additions & 7 deletions models/names_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,12 @@
class Name(db.Model):
"""
Specifies how names are stored in the database for Estonian localization
@param name: the name as a string
@param genitive: the name in genitive case
"""
__tablename__ = "names_cases"

name: str = Column(VARCHAR(255), primary_key=True, nullable=False)
genitive: str = Column(VARCHAR(255), nullable=False)

def __init__(self, name: str, genitive: str):
self.name = name
self.genitive = genitive

def __repr__(self):
return "<id {}>".format(self.id)

Expand Down
Loading

0 comments on commit dce26f1

Please sign in to comment.