class News(db.Model): "Represent an article from a feed." id = db.Column(db.Integer(), primary_key=True) entry_id = db.Column(db.String(), nullable=False) link = db.Column(db.String()) title = db.Column(db.String()) content = db.Column(db.String()) published = db.Column(db.DateTime(), default=datetime.utcnow) retrieved_date = db.Column(db.DateTime(), default=datetime.utcnow) project_id = db.Column(db.Integer(), db.ForeignKey("project.id")) feed_id = db.Column(db.Integer(), db.ForeignKey("feed.id")) # index idx_article_pid = Index("project_id") idx_article_pid_fid = Index("project_id", "feed_id") def __repr__(self): return "<News(id=%d, entry_id=%s, title=%r, date=%r, retrieved_date=%r)>" % ( self.id, self.entry_id, self.title, self.published, self.retrieved_date, )
class User(db.Model, UserMixin): """ Represent a user. """ id = db.Column(db.Integer, primary_key=True) login = db.Column(db.String(), unique=True, nullable=False) pwdhash = db.Column(db.String(), nullable=False) created_at = db.Column(db.DateTime(), default=datetime.utcnow()) last_seen = db.Column(db.DateTime(), default=datetime.utcnow()) apikey = db.Column(db.String(), default=secrets.token_urlsafe(50)) public_profile = db.Column(db.Boolean(), default=True) # user rights is_active = db.Column(db.Boolean(), default=False) is_admin = db.Column(db.Boolean(), default=False) is_api = db.Column(db.Boolean(), default=False) # relationship positions = db.relationship( "Project", backref="manager", lazy="dynamic", foreign_keys=[Project.manager_id] ) contributions = db.relationship( "Project", backref="submitter", lazy="dynamic", foreign_keys=[Project.submitter_id], ) def __repr__(self): return self.login def get_id(self): """ Return the id of the user. """ return self.id def generate_apikey(self): self.apikey = secrets.token_urlsafe(50) def check_password(self, password): """ Check the password of the user. """ return check_password_hash(self.pwdhash, password) @validates("login") def validates_login(self, key, value): assert 3 <= len(value) <= 30, AssertionError("maximum length for login: 30") return re.sub(r"[^a-zA-Z0-9_\.]", "", value.strip())
class Organization(db.Model): """Represent an organization.""" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), unique=True) description = db.Column(db.String(), default="") short_description = db.Column(db.String(400)) organization_type = db.Column(db.String(100), default="") website = db.Column(db.String(), default="") last_updated = db.Column(db.DateTime(), default=datetime.utcnow) cve_vendor = db.Column(db.String(), default="") # foreign keys icon_url = db.Column(db.String(), db.ForeignKey("icon.url"), default=None) # relationship projects = db.relationship( Project, backref="organization", lazy="dynamic", cascade="all,delete-orphan" ) @validates("name") def validates_name(self, key, value): assert len(value) <= 100, AssertionError("maximum length for name: 100") return value.replace(" ", "").strip()
class Feed(db.Model): """ Represent a feed. """ id = db.Column(db.Integer(), primary_key=True) link = db.Column(db.String(), nullable=False) created_date = db.Column(db.DateTime(), default=datetime.utcnow) project_id = db.Column(db.Integer(), db.ForeignKey("project.id")) # relationship news = db.relationship( News, backref="source", lazy="dynamic", cascade="all,delete-orphan", order_by=desc(News.published), ) # index idx_feed_pid = Index("project_id") def __repr__(self): return "<Feed %r>" % (self.link)
class Language(db.Model): """Represent a language.""" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(), default="", nullable=False, unique=True) created_at = db.Column(db.DateTime(), default=datetime.utcnow()) def __str__(self): return self.name
class Code(db.Model): """Represent a source code (a repository).""" id = db.Column(db.Integer(), primary_key=True) repository_url = db.Column(db.String(), nullable=False) scm_type = db.Column(db.String(), nullable=False, default="Git") last_updated = db.Column(db.DateTime(), default=datetime.utcnow()) # foreign keys project_id = db.Column(db.Integer(), db.ForeignKey("project.id"), default=None)
class CVE(db.Model): """Represent a CVE.""" id = db.Column(db.Integer, primary_key=True) cve_id = db.Column(db.String(), nullable=False) summary = db.Column(db.String(), default="") published_at = db.Column(db.DateTime(), default=datetime.utcnow) # foreign keys project_id = db.Column(db.Integer(), db.ForeignKey("project.id"), default=None)
class Submission(db.Model): """Represent a submission.""" id = db.Column(db.Integer, primary_key=True) project_name = db.Column(db.String(100), unique=True) project_description = db.Column(db.String()) project_website = db.Column(db.String()) reviewed = db.Column(db.Boolean(), default=False) accepted = db.Column(db.Boolean(), default=False) created_at = db.Column(db.DateTime(), default=datetime.utcnow) # relationships licenses = db.relationship("License", secondary=lambda: association_table_license, backref="submissions")
class License(db.Model): """Represent a license. https://opensource.org/licenses/alphabetical """ id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(), default="", nullable=False, unique=True) license_id = db.Column(db.String(), default="", nullable=False, unique=True) created_at = db.Column(db.DateTime(), default=datetime.utcnow()) def __str__(self): return self.name
class Release(db.Model): """Represent a release.""" id = db.Column(db.Integer, primary_key=True) version = db.Column(db.String(), default="", nullable=False) state = db.Column(db.String(), default="") # ie: stable scope = db.Column(db.String(), default="") # ie: minor bugfix feature changes = db.Column(db.String(), default="") release_url = db.Column(db.String(), default="") download_url = db.Column(db.String(), default="") published_at = db.Column(db.DateTime(), default=datetime.utcnow()) # foreign keys project_id = db.Column(db.Integer(), db.ForeignKey("project.id"), default=None)
class Project(db.Model): """Represent a project.""" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), unique=True) description = db.Column(db.String()) short_description = db.Column(db.String(400)) website = db.Column(db.String()) last_updated = db.Column(db.DateTime(), default=datetime.utcnow) # if cve_vendor is the empty string use the parent property # (organization.cve_vendor) cve_vendor = db.Column(db.String(), default="") cve_product = db.Column(db.String(), unique=True, nullable=False) automatic_release_tracking = db.Column(db.String()) # foreign keys organization_id = db.Column(db.Integer(), db.ForeignKey("organization.id")) submitter_id = db.Column(db.Integer(), db.ForeignKey("user.id"), default=None) manager_id = db.Column(db.Integer(), db.ForeignKey("user.id")) icon_url = db.Column(db.String(), db.ForeignKey("icon.url"), default=None) # relationships code_locations = db.relationship("Code", backref="project", lazy="dynamic", cascade="all,delete-orphan") tag_objs = db.relationship( "Tag", back_populates="project", cascade="all,delete-orphan", lazy=False, foreign_keys="[Tag.project_id]", ) tags = association_proxy("tag_objs", "text") licenses = db.relationship("License", secondary=lambda: association_table_license, backref="projects") languages = db.relationship("Language", secondary=lambda: association_table_language, backref="projects") dependencies = db.relationship( "Project", secondary=lambda: association_table_project, primaryjoin=association_table_project.c.project_dependent_id == id, secondaryjoin=association_table_project.c.project_dependency_id == id, backref="dependents", ) cves = db.relationship("CVE", backref="project", lazy="dynamic", cascade="all,delete-orphan") releases = db.relationship( "Release", backref="project", lazy="dynamic", cascade="all,delete-orphan", order_by="desc(Release.published_at)", ) news = db.relationship("News", backref="project", lazy="dynamic", cascade="all,delete-orphan") @validates("name") def validates_name(self, key, value): assert len(value) <= 100, AssertionError( "maximum length for name: 100") return value.replace(" ", "").strip() def __repr__(self): return "<Name %r>" % (self.name)