class EquipmentType(db.Model): __tablename__ = 'equipment_types' __table_args__ = (db.UniqueConstraint('name', 'location_id'), { 'schema': 'roombooking' }) id = db.Column(db.Integer, primary_key=True) parent_id = db.Column(db.Integer, db.ForeignKey('roombooking.equipment_types.id')) name = db.Column(db.String, nullable=False, index=True) location_id = db.Column(db.Integer, db.ForeignKey('roombooking.locations.id'), nullable=False) children = db.relationship('EquipmentType', backref=db.backref('parent', remote_side=[id])) # relationship backrefs: # - location (Location.equipment_types) # - parent (EquipmentType.children) # - reservations (Reservation.used_equipment) # - rooms (Room.available_equipment) @return_ascii def __repr__(self): return u'<EquipmentType({0}, {1}, {2})>'.format( self.id, self.name, self.location_id)
class RoomAttribute(db.Model): __tablename__ = 'room_attributes' __table_args__ = (db.UniqueConstraint('name', 'location_id'), { 'schema': 'roombooking' }) id = db.Column(db.Integer, primary_key=True) parent_id = db.Column(db.Integer, db.ForeignKey('roombooking.room_attributes.id')) name = db.Column(db.String, nullable=False, index=True) title = db.Column(db.String, nullable=False) location_id = db.Column(db.Integer, db.ForeignKey('roombooking.locations.id'), nullable=False) type = db.Column(db.String, nullable=False) is_required = db.Column(db.Boolean, nullable=False) is_hidden = db.Column(db.Boolean, nullable=False) children = db.relationship('RoomAttribute', backref=db.backref('parent', remote_side=[id])) # relationship backrefs: # - location (Location.attributes) # - parent (RoomAttribute.children) # - room_associations (RoomAttributeAssociation.attribute) @return_ascii def __repr__(self): return u'<RoomAttribute({}, {}, {})>'.format(self.id, self.name, self.location.name)
class SuggestedCategory(db.Model): __tablename__ = 'suggested_categories' __table_args__ = {'schema': 'users'} user_id = db.Column( db.Integer, db.ForeignKey('users.users.id'), primary_key=True, index=True, autoincrement=False ) category_id = db.Column( db.Integer, db.ForeignKey('categories.categories.id'), primary_key=True, index=True, autoincrement=False ) is_ignored = db.Column( db.Boolean, nullable=False, default=False ) score = db.Column( db.Float, nullable=False, default=0 ) category = db.relationship( 'Category', lazy=False, backref=db.backref( 'suggestions', lazy=True, cascade='all, delete-orphan' ) ) # relationship backrefs: # - user (User.suggested_categories) @return_ascii def __repr__(self): return format_repr(self, 'user_id', 'category_id', 'score', is_ignored=False) @classmethod def merge_users(cls, target, source): """Merge the suggestions for two users. :param target: The target user of the merge. :param source: The user that is being merged into `target`. """ target_suggestions = {x.category: x for x in target.suggested_categories} for suggestion in source.suggested_categories: new_suggestion = target_suggestions.get(suggestion.category) or cls(user=target, category=suggestion.category) new_suggestion.score = max(new_suggestion.score, suggestion.score) new_suggestion.is_ignored = new_suggestion.is_ignored or suggestion.is_ignored db.session.flush()
class StaticSite(StoredFileMixin, db.Model): """Static site for an fossir event.""" __tablename__ = 'static_sites' __table_args__ = {'schema': 'events'} # StoredFileMixin settings add_file_date_column = False file_required = False #: Entry ID id = db.Column(db.Integer, primary_key=True) #: ID of the event event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), index=True, nullable=False) #: The state of the static site (a :class:`StaticSiteState` member) state = db.Column(PyIntEnum(StaticSiteState), default=StaticSiteState.pending, nullable=False) #: The date and time the static site was requested requested_dt = db.Column(UTCDateTime, default=now_utc, nullable=False) #: ID of the user who created the static site creator_id = db.Column(db.Integer, db.ForeignKey('users.users.id'), index=True, nullable=False) #: The user who created the static site creator = db.relationship('User', lazy=False, backref=db.backref('static_sites', lazy='dynamic')) #: The Event this static site is associated with event = db.relationship('Event', lazy=True, backref=db.backref('static_sites', lazy='dynamic')) @property def locator(self): return {'confId': self.event_id, 'id': self.id} def _build_storage_path(self): path_segments = ['event', strict_unicode(self.event.id), 'static'] self.assign_id() filename = '{}-{}'.format(self.id, self.filename) path = posixpath.join(*(path_segments + [filename])) return config.STATIC_SITE_STORAGE, path @return_ascii def __repr__(self): return format_repr(self, 'id', 'event_id', 'state')
class PaperCompetence(db.Model): __tablename__ = 'competences' __table_args__ = (db.UniqueConstraint('user_id', 'event_id'), {'schema': 'event_paper_reviewing'}) id = db.Column( db.Integer, primary_key=True ) user_id = db.Column( db.Integer, db.ForeignKey('users.users.id'), index=True, nullable=False ) event_id = db.Column( db.Integer, db.ForeignKey('events.events.id'), index=True, nullable=False ) competences = db.Column( ARRAY(db.String), nullable=False, default=[] ) event = db.relationship( 'Event', lazy=True, backref=db.backref( 'paper_competences', cascade='all, delete-orphan', lazy=True ) ) user = db.relationship( 'User', lazy=True, backref=db.backref( 'paper_competences', lazy='dynamic' ) ) @return_ascii def __repr__(self): return format_repr(self, 'id', 'user_id', 'event_id', _text=', '.join(self.competences))
class UserSetting(JSONSettingsBase, db.Model): """User-specific settings""" __table_args__ = (db.Index(None, 'user_id', 'module', 'name'), db.Index(None, 'user_id', 'module'), db.UniqueConstraint('user_id', 'module', 'name'), db.CheckConstraint('module = lower(module)', 'lowercase_module'), db.CheckConstraint('name = lower(name)', 'lowercase_name'), { 'schema': 'users' }) user_id = db.Column(db.Integer, db.ForeignKey('users.users.id'), nullable=False, index=True) user = db.relationship('User', lazy=True, backref=db.backref('_all_settings', lazy='dynamic', cascade='all, delete-orphan')) @return_ascii def __repr__(self): return '<UserSetting({}, {}, {}, {!r})>'.format( self.user_id, self.module, self.name, self.value)
def contribution_field_id(cls): return db.Column( db.Integer, db.ForeignKey('events.contribution_fields.id', name='fk_{}_contribution_field'.format(cls.__tablename__)), primary_key=True, index=True )
def revision_id(cls): return db.Column( db.Integer, db.ForeignKey('event_paper_reviewing.revisions.id'), index=True, nullable=False )
class CategorySetting(JSONSettingsBase, db.Model): @strict_classproperty @staticmethod def __auto_table_args(): return (db.Index(None, 'category_id', 'module', 'name'), db.Index(None, 'category_id', 'module'), db.UniqueConstraint('category_id', 'module', 'name'), { 'schema': 'categories' }) @declared_attr def __table_args__(cls): return auto_table_args(cls) category_id = db.Column(db.Integer, db.ForeignKey('categories.categories.id'), index=True, nullable=False) category = db.relationship('Category', lazy=True, backref=db.backref('settings', lazy='dynamic')) @return_ascii def __repr__(self): return '<CategorySetting({}, {}, {}, {!r})>'.format( self.category_id, self.module, self.name, self.value)
def event_id(cls): return db.Column( db.Integer, db.ForeignKey('events.events.id'), nullable=False, index=True )
class LegacyCategoryMapping(db.Model): """Legacy category ID mapping Legacy categories have non-numeric IDs which are not supported by any new code. This mapping maps them to proper integer IDs to avoid breaking things. """ __tablename__ = 'legacy_id_map' __table_args__ = {'schema': 'categories'} legacy_category_id = db.Column(db.String, primary_key=True, index=True) category_id = db.Column(db.Integer, db.ForeignKey('categories.categories.id'), index=True, primary_key=True, autoincrement=False) category = db.relationship('Category', lazy=True, backref=db.backref('legacy_mapping', uselist=False, lazy=True)) @return_ascii def __repr__(self): return '<LegacyCategoryMapping({}, {})>'.format( self.legacy_category_id, self.category_id)
class SessionPrincipal(PrincipalRolesMixin, db.Model): __tablename__ = 'session_principals' principal_backref_name = 'in_session_acls' principal_for = 'Session' unique_columns = ('session_id', ) disallowed_protection_modes = frozenset() allow_emails = True @declared_attr def __table_args__(cls): return auto_table_args(cls, schema='events') #: The ID of the acl entry id = db.Column(db.Integer, primary_key=True) #: The ID of the associated session session_id = db.Column(db.Integer, db.ForeignKey('events.sessions.id'), nullable=False, index=True) # relationship backrefs: # - session (Session.acl_entries) @return_ascii def __repr__(self): return format_repr(self, 'id', 'session_id', 'principal', read_access=False, full_access=False, roles=[])
def abstract_id(cls): return db.Column( db.Integer, db.ForeignKey('event_abstracts.abstracts.id'), index=True, nullable=False )
class EventPrincipal(PrincipalRolesMixin, db.Model): __tablename__ = 'principals' principal_backref_name = 'in_event_acls' principal_for = 'Event' unique_columns = ('event_id', ) allow_emails = True allow_networks = True @declared_attr def __table_args__(cls): return auto_table_args(cls, schema='events') #: The ID of the acl entry id = db.Column(db.Integer, primary_key=True) #: The ID of the associated event event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), nullable=False, index=True) # relationship backrefs: # - event (Event.acl_entries) @return_ascii def __repr__(self): return format_repr(self, 'id', 'event_id', 'principal', read_access=False, full_access=False, roles=[])
class LegacyImageMapping(db.Model): """Legacy image id mapping Legacy images had event-unique numeric ids. Using this mapping we can resolve old ones to their new id. """ __tablename__ = 'legacy_image_id_map' __table_args__ = {'schema': 'events'} event_id = db.Column( db.Integer, db.ForeignKey('events.events.id'), primary_key=True, index=True, autoincrement=False ) legacy_image_id = db.Column( db.Integer, primary_key=True, index=True, autoincrement=False ) image_id = db.Column( db.Integer, db.ForeignKey('events.image_files.id'), nullable=False, index=True ) image = db.relationship( 'ImageFile', lazy=False, backref=db.backref( 'legacy_mapping', cascade='all, delete-orphan', uselist=False, lazy=True ) ) @return_ascii def __repr__(self): return format_repr(self, 'legacy_image_id', 'image_id')
class LegacySubContributionMapping(db.Model): """Legacy subcontribution id mapping Legacy subcontributions had ids unique only within their event and contribution. This table maps those ids to the new globally unique subcontribution id. """ __tablename__ = 'legacy_subcontribution_id_map' __table_args__ = {'schema': 'events'} event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), primary_key=True, autoincrement=False) legacy_contribution_id = db.Column(db.String, primary_key=True) legacy_subcontribution_id = db.Column(db.String, primary_key=True) subcontribution_id = db.Column( db.Integer, db.ForeignKey('events.subcontributions.id', name='fk_legacy_subcontribution_id_map_subcontribution'), nullable=False, index=True) event = db.relationship('Event', lazy=True, backref=db.backref( 'legacy_subcontribution_mappings', cascade='all, delete-orphan', lazy='dynamic')) subcontribution = db.relationship('SubContribution', lazy=False, backref=db.backref( 'legacy_mapping', cascade='all, delete-orphan', uselist=False, lazy=True)) @return_ascii def __repr__(self): return format_repr(self, 'event_id', 'legacy_contribution_id', 'legacy_subcontribution_id', 'subcontribution_id')
class AbstractEmailTemplate(db.Model): """Represents an email template for abstracts notifications.""" __tablename__ = 'email_templates' __table_args__ = {'schema': 'event_abstracts'} id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String, nullable=False) event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), index=True, nullable=False) #: The relative position of the template in the list of templates position = db.Column(db.Integer, nullable=False, default=_get_next_position) #: The address to use as Reply-To in the email reply_to_address = db.Column(db.String, nullable=False) #: The subject of the email subject = db.Column(db.String, nullable=False) #: The body of the template body = db.Column(db.Text, nullable=False, default='') #: List of extra email addresses to be added as CC in the email extra_cc_emails = db.Column( ARRAY(db.String), nullable=False, default=[], ) #: Whether to include the submitter's email address as To for emails include_submitter = db.Column(db.Boolean, nullable=False, default=False) #: Whether to include authors' email addresses as To for emails include_authors = db.Column(db.Boolean, nullable=False, default=False) #: Whether to include co-authors' email addresses as CC for emails include_coauthors = db.Column(db.Boolean, nullable=False, default=False) #: Whether to stop checking the rest of the conditions when a match is found stop_on_match = db.Column(db.Boolean, nullable=False, default=True) #: Conditions need to be met to send the email rules = db.Column(JSON, nullable=False) event = db.relationship('Event', lazy=True, backref=db.backref('abstract_email_templates', lazy=True)) # relationship backrefs: # - logs (AbstractEmailLogEntry.email_template) @locator_property def locator(self): return dict(self.event.locator, email_tpl_id=self.id) @return_ascii def __repr__(self): return format_repr(self, 'id', 'event_id', _text=self.title)
class DesignerImageFile(StoredFileMixin, db.Model): __tablename__ = 'designer_image_files' __table_args__ = {'schema': 'fossir'} # Image files are not version-controlled version_of = None #: The ID of the file id = db.Column( db.Integer, primary_key=True ) #: The designer template the image belongs to template_id = db.Column( db.Integer, db.ForeignKey('fossir.designer_templates.id'), nullable=False, index=True ) template = db.relationship( 'DesignerTemplate', lazy=False, foreign_keys=template_id, backref=db.backref( 'images', cascade='all, delete-orphan', lazy=True ) ) @property def download_url(self): return url_for('designer.download_image', self) @property def locator(self): return dict(self.template.locator, image_id=self.id, filename=self.filename) def _build_storage_path(self): path_segments = ['designer_templates', strict_unicode(self.template.id), 'images'] self.assign_id() filename = '{}-{}'.format(self.id, self.filename) path = posixpath.join(*(path_segments + [filename])) return config.ATTACHMENT_STORAGE, path @return_ascii def __repr__(self): return '<DesignerImageFile({}, {}, {}, {})>'.format( self.id, self.template_id, self.filename, self.content_type )
class SurveyAnswer(db.Model): __tablename__ = 'answers' __table_args__ = {'schema': 'event_surveys'} #: The ID of the submission submission_id = db.Column(db.Integer, db.ForeignKey('event_surveys.submissions.id'), primary_key=True) #: The ID of the question question_id = db.Column(db.Integer, db.ForeignKey('event_surveys.items.id'), primary_key=True) #: The user's answer (no, not 42!) to the question data = db.Column(JSON, nullable=False) #: The list of answers question = db.relationship('SurveyQuestion', lazy=True, backref=db.backref('answers', cascade='all, delete-orphan', lazy=True)) # relationship backrefs: # - submission (SurveySubmission.answers) @property def is_empty(self): return self.question.field.is_value_empty(self) @return_ascii def __repr__(self): return '<SurveyAnswer({}, {}): {}>'.format(self.submission_id, self.question_id, self.data) @property def answer_data(self): return self.question.field.get_friendly_value(self.data)
class LegacySessionBlockMapping(db.Model): """Legacy session block id mapping Legacy sessions blocks had ids unique only within their session. """ __tablename__ = 'legacy_session_block_id_map' __table_args__ = {'schema': 'events'} event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), primary_key=True, autoincrement=False) legacy_session_id = db.Column(db.String, primary_key=True) legacy_session_block_id = db.Column(db.String, primary_key=True) session_block_id = db.Column(db.Integer, db.ForeignKey('events.session_blocks.id'), nullable=False, index=True) event = db.relationship('Event', lazy=True, backref=db.backref('legacy_session_block_mappings', cascade='all, delete-orphan', lazy='dynamic')) session_block = db.relationship('SessionBlock', lazy=False, backref=db.backref( 'legacy_mapping', cascade='all, delete-orphan', uselist=False, lazy=True)) @return_ascii def __repr__(self): return format_repr(self, 'event_id', 'legacy_session_id', 'legacy_session_block_id', 'session_block_id')
class LegacyRegistrationMapping(db.Model): """Legacy registration id/token mapping Legacy registrations had tokens which are not compatible with the new UUID-based ones. """ __tablename__ = 'legacy_registration_map' __table_args__ = {'schema': 'event_registration'} event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), primary_key=True, autoincrement=False) legacy_registrant_id = db.Column(db.Integer, primary_key=True, autoincrement=False) legacy_registrant_key = db.Column(db.String, nullable=False) registration_id = db.Column( db.Integer, db.ForeignKey('event_registration.registrations.id'), index=True, nullable=False) registration = db.relationship('Registration', lazy=False, backref=db.backref( 'legacy_mapping', cascade='all, delete-orphan', uselist=False, lazy=True)) @return_ascii def __repr__(self): return format_repr(self, 'event_id', 'legacy_registrant_id', 'legacy_registrant_key', 'registration_id')
class RoomAttributeAssociation(db.Model): __tablename__ = 'room_attribute_values' __table_args__ = {'schema': 'roombooking'} attribute_id = db.Column(db.Integer, db.ForeignKey('roombooking.room_attributes.id', ), primary_key=True) room_id = db.Column(db.Integer, db.ForeignKey('roombooking.rooms.id', ), primary_key=True) value = db.Column(JSON) attribute = db.relationship('RoomAttribute', backref=db.backref( 'room_associations', cascade='all, delete-orphan')) # relationship backrefs: # - room (Room.attributes) @return_ascii def __repr__(self): return u'<RoomAttributeAssociation({0}, {1}, {2})>'.format( self.room_id, self.attribute.name, self.value)
class IPNetwork(db.Model): __tablename__ = 'ip_networks' __table_args__ = {'schema': 'fossir'} group_id = db.Column(db.Integer, db.ForeignKey('fossir.ip_network_groups.id'), primary_key=True, autoincrement=False) network = db.Column(PyIPNetwork, primary_key=True, nullable=False) # relationship backrefs: # - group (IPNetworkGroup._networks) @return_ascii def __repr__(self): return format_repr(self, 'group_id', 'network')
class BlockingPrincipal(PrincipalMixin, db.Model): __tablename__ = 'blocking_principals' __table_args__ = {'schema': 'roombooking'} principal_backref_name = 'in_blocking_acls' unique_columns = ('blocking_id', ) id = db.Column(db.Integer, primary_key=True) blocking_id = db.Column(db.Integer, db.ForeignKey('roombooking.blockings.id'), nullable=False) # relationship backrefs: # - blocking (Blocking._allowed) @return_ascii def __repr__(self): return '<BlockingPrincipal({}, {}, {})>'.format( self.id, self.blocking_id, self.principal)
class ContributionReference(ReferenceModelBase): __tablename__ = 'contribution_references' __table_args__ = {'schema': 'events'} reference_backref_name = 'contribution_references' contribution_id = db.Column( db.Integer, db.ForeignKey('events.contributions.id'), nullable=False, index=True ) # relationship backrefs: # - contribution (Contribution.references) @return_ascii def __repr__(self): return format_repr(self, 'id', 'contribution_id', 'reference_type_id', _text=self.value)
class AbstractFile(StoredFileMixin, db.Model): __tablename__ = 'files' __table_args__ = {'schema': 'event_abstracts'} # StoredFileMixin settings add_file_date_column = False id = db.Column(db.Integer, primary_key=True) abstract_id = db.Column(db.Integer, db.ForeignKey('event_abstracts.abstracts.id'), nullable=False, index=True) abstract = db.relationship('Abstract', lazy=True, backref=db.backref( 'files', lazy=True, cascade='all, delete-orphan')) @property def locator(self): return dict(self.abstract.locator, file_id=self.id, filename=self.filename) def _build_storage_path(self): self.abstract.assign_id() path_segments = [ 'event', strict_unicode(self.abstract.event.id), 'abstracts', strict_unicode(self.abstract.id) ] self.assign_id() filename = '{}-{}'.format(self.id, self.filename) path = posixpath.join(*(path_segments + [filename])) return config.ATTACHMENT_STORAGE, path @return_ascii def __repr__(self): return format_repr(self, 'id', 'abstract_id', content_type=None, _text=text_to_repr(self.filename))
class PaperTemplate(StoredFileMixin, db.Model): __tablename__ = 'templates' __table_args__ = {'schema': 'event_paper_reviewing'} # StoredFileMixin settings add_file_date_column = False id = db.Column(db.Integer, primary_key=True) event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), index=True, nullable=False) name = db.Column(db.String, nullable=False) description = db.Column(db.Text, nullable=False, default='') event = db.relationship('Event', lazy=True, backref=db.backref('paper_templates', cascade='all, delete-orphan', lazy=True)) @return_ascii def __repr__(self): return format_repr(self, 'id', 'event_id', 'filename', content_type=None) @locator_property def locator(self): return dict(self.event.locator, template_id=self.id, filename=self.filename) def _build_storage_path(self): self.assign_id() path_segments = [ 'event', strict_unicode(self.event.id), 'paper_templates' ] path = posixpath.join(*(path_segments + ['{}_{}'.format(self.id, self.filename)])) return config.ATTACHMENT_STORAGE, path
class ImageFile(StoredFileMixin, db.Model): __tablename__ = 'image_files' __table_args__ = {'schema': 'events'} # Image files are not version-controlled version_of = None #: The ID of the file id = db.Column(db.Integer, primary_key=True) #: The event the image belongs to event_id = db.Column(db.Integer, db.ForeignKey('events.events.id'), nullable=False, index=True) event = db.relationship('Event', lazy=False, backref=db.backref('layout_images', lazy='dynamic')) # relationship backrefs: # - legacy_mapping (LegacyImageMapping.image) @property def locator(self): return dict(self.event.locator, image_id=self.id, filename=self.filename) def _build_storage_path(self): path_segments = ['event', strict_unicode(self.event.id), 'images'] self.assign_id() filename = '{}-{}'.format(self.id, self.filename) path = posixpath.join(*(path_segments + [filename])) return config.ATTACHMENT_STORAGE, path @return_ascii def __repr__(self): return '<ImageFile({}, {}, {}, {})>'.format(self.id, self.event_id, self.filename, self.content_type)
class ContributionFieldValue(ContributionFieldValueBase): __tablename__ = 'contribution_field_values' __table_args__ = {'schema': 'events'} contribution_field_backref_name = 'contribution_values' contribution_id = db.Column( db.Integer, db.ForeignKey('events.contributions.id'), index=True, nullable=False, primary_key=True ) # relationship backrefs: # - contribution (Contribution.field_values) @return_ascii def __repr__(self): text = text_to_repr(self.data) if isinstance(self.data, unicode) else self.data return format_repr(self, 'contribution_id', 'contribution_field_id', _text=text)
class ReservationEditLog(db.Model): __tablename__ = 'reservation_edit_logs' __table_args__ = {'schema': 'roombooking'} id = db.Column(db.Integer, primary_key=True) timestamp = db.Column(UTCDateTime, nullable=False, default=now_utc) info = db.Column(ARRAY(db.String), nullable=False) user_name = db.Column(db.String, nullable=False) reservation_id = db.Column(db.Integer, db.ForeignKey('roombooking.reservations.id'), nullable=False, index=True) # relationship backrefs: # - reservation (Reservation.edit_logs) @return_ascii def __repr__(self): return u'<ReservationEditLog({0}, {1}, {2}, {3})>'.format( self.user_name, self.reservation_id, self.timestamp, self.info)