class Control(synchronizable.Synchronizable, categorizable.Categorizable, WithLastAssessmentDate, synchronizable.RoleableSynchronizable, Relatable, mixins.CustomAttributable, Personable, PublicDocumentable, mixins.LastDeprecatedTimeboxed, mixins.TestPlanned, comment.ExternalCommentable, WithSimilarityScore, base.ContextRBAC, mixins.BusinessObject, Indexed, mixins.Folderable, proposal.Proposalable, db.Model): """Control model definition.""" __tablename__ = 'controls' company_control = deferred(db.Column(db.Boolean), 'Control') directive_id = deferred( db.Column(db.Integer, db.ForeignKey('directives.id')), 'Control') version = deferred(db.Column(db.String), 'Control') fraud_related = deferred(db.Column(db.Boolean), 'Control') key_control = deferred(db.Column(db.Boolean), 'Control') active = deferred(db.Column(db.Boolean), 'Control') kind = deferred(db.Column(db.String), "Control") means = deferred(db.Column(db.String), "Control") verify_frequency = deferred(db.Column(db.String), "Control") review_status = deferred(db.Column(db.String, nullable=True), "Control") review_status_display_name = deferred(db.Column(db.String, nullable=True), "Control") # GGRCQ attributes due_date = db.Column(db.Date, nullable=True) created_by_id = db.Column(db.Integer, nullable=False) # pylint: disable=no-self-argument @declared_attr def created_by(cls): """Relationship to user referenced by created_by_id.""" return utils.person_relationship(cls.__name__, "created_by_id") last_submitted_at = db.Column(db.DateTime, nullable=True) last_submitted_by_id = db.Column(db.Integer, nullable=True) # pylint: disable=no-self-argument @declared_attr def last_submitted_by(cls): """Relationship to user referenced by last_submitted_by_id.""" return utils.person_relationship(cls.__name__, "last_submitted_by_id") last_verified_at = db.Column(db.DateTime, nullable=True) last_verified_by_id = db.Column(db.Integer, nullable=True) # pylint: disable=no-self-argument @declared_attr def last_verified_by(cls): """Relationship to user referenced by last_verified_by_id.""" return utils.person_relationship(cls.__name__, "last_verified_by_id") _title_uniqueness = False _custom_publish = { 'created_by': ggrc_utils.created_by_stub, 'last_submitted_by': ggrc_utils.last_submitted_by_stub, 'last_verified_by': ggrc_utils.last_verified_by_stub, } # REST properties _api_attrs = reflection.ApiAttributes( 'active', 'company_control', 'directive', 'fraud_related', 'key_control', 'kind', 'means', 'verify_frequency', 'version', 'review_status', 'review_status_display_name', 'due_date', reflection.ExternalUserAttribute('created_by', force_create=True), 'last_submitted_at', reflection.ExternalUserAttribute('last_submitted_by', force_create=True), 'last_verified_at', reflection.ExternalUserAttribute('last_verified_by', force_create=True), ) _fulltext_attrs = [ 'active', 'company_control', 'directive', attributes.BooleanFullTextAttr('fraud_related', 'fraud_related', true_value="yes", false_value="no"), attributes.BooleanFullTextAttr('key_control', 'key_control', true_value="key", false_value="non-key"), 'kind', 'means', 'verify_frequency', 'version', 'review_status_display_name', ] _sanitize_html = [ 'version', ] @classmethod def indexed_query(cls): return super(Control, cls).indexed_query().options( orm.Load(cls).undefer_group("Control_complete"), orm.Load(cls).joinedload("directive").undefer_group( "Directive_complete"), ) _include_links = [] _aliases = { "kind": "Kind/Nature", "means": "Type/Means", "verify_frequency": "Frequency", "fraud_related": "Fraud Related", "key_control": { "display_name": "Significance", "description": "Allowed values are:\nkey\nnon-key\n---", }, "test_plan": "Assessment Procedure", "review_status": { "display_name": "Review State", "mandatory": False, "filter_only": True }, "review_status_display_name": { "display_name": "Review Status", "mandatory": False }, } @classmethod def eager_query(cls, **kwargs): query = super(Control, cls).eager_query(**kwargs) return cls.eager_inclusions(query, Control._include_links).options( orm.joinedload('directive'), ) def log_json(self): out_json = super(Control, self).log_json() out_json["created_by"] = ggrc_utils.created_by_stub(self) out_json["last_submitted_by"] = ggrc_utils.last_submitted_by_stub(self) out_json["last_verified_by"] = ggrc_utils.last_verified_by_stub(self) # so that event log can refer to deleted directive if self.directive: out_json["mapped_directive"] = self.directive.display_name return out_json @validates('review_status') def validate_review_status(self, _, value): # pylint: disable=no-self-use """Add explicit non-nullable validation.""" if value is None: raise ValidationError( "review_status for the object is not specified") return value # pylint: disable=invalid-name @validates('review_status_display_name') def validate_review_status_display_name(self, _, value): """Add explicit non-nullable validation.""" # pylint: disable=no-self-use,invalid-name if value is None: raise ValidationError( "review_status_display_name for the object is not specified") return value
class Risk(synchronizable.Synchronizable, synchronizable.RoleableSynchronizable, mixins.ExternalCustomAttributable, Relatable, PublicDocumentable, comment.ExternalCommentable, mixins.TestPlanned, mixins.LastDeprecatedTimeboxed, mixins.base.ContextRBAC, mixins.BusinessObject, mixins.Folderable, Indexed, db.Model): """Basic Risk model.""" __tablename__ = 'risks' # GGRCQ attributes external_id = db.Column(db.Integer, nullable=False) due_date = db.Column(db.Date, nullable=True) created_by_id = db.Column(db.Integer, nullable=False) review_status = deferred(db.Column(db.String, nullable=True), "Risk") review_status_display_name = deferred(db.Column(db.String, nullable=True), "Risk") # pylint: disable=no-self-argument @declared_attr def created_by(cls): """Relationship to user referenced by created_by_id.""" return utils.person_relationship(cls.__name__, "created_by_id") last_submitted_at = db.Column(db.DateTime, nullable=True) last_submitted_by_id = db.Column(db.Integer, nullable=True) @declared_attr def last_submitted_by(cls): """Relationship to user referenced by last_submitted_by_id.""" return utils.person_relationship(cls.__name__, "last_submitted_by_id") last_verified_at = db.Column(db.DateTime, nullable=True) last_verified_by_id = db.Column(db.Integer, nullable=True) @declared_attr def last_verified_by(cls): """Relationship to user referenced by last_verified_by_id.""" return utils.person_relationship(cls.__name__, "last_verified_by_id") # Overriding mixin to make mandatory @declared_attr def description(cls): # pylint: disable=no-self-argument return deferred(db.Column(db.Text, nullable=False, default=u""), cls.__name__) risk_type = db.Column(db.Text, nullable=True) threat_source = db.Column(db.Text, nullable=True) threat_event = db.Column(db.Text, nullable=True) vulnerability = db.Column(db.Text, nullable=True) @validates('review_status') def validate_review_status(self, _, value): """Add explicit non-nullable validation.""" # pylint: disable=no-self-use if value is None: raise exceptions.ValidationError( "Review status for the object is not specified") return value @validates('review_status_display_name') def validate_review_status_display_name(self, _, value): """Add explicit non-nullable validation.""" # pylint: disable=no-self-use # pylint: disable=invalid-name if value is None: raise exceptions.ValidationError( "Review status display for the object is not specified") return value _sanitize_html = [ 'risk_type', 'threat_source', 'threat_event', 'vulnerability' ] _fulltext_attrs = [ 'risk_type', 'threat_source', 'threat_event', 'vulnerability', 'review_status_display_name', attributes.DateFullTextAttr('due_date', 'due_date'), attributes.DatetimeFullTextAttr('last_submitted_at', 'last_submitted_at'), attributes.DatetimeFullTextAttr('last_verified_at', 'last_verified_at'), attributes.FullTextAttr("created_by", "created_by", ["email", "name"]), attributes.FullTextAttr("last_submitted_by", "last_submitted_by", ["email", "name"]), attributes.FullTextAttr("last_verified_by", "last_verified_by", ["email", "name"]) ] _custom_publish = { 'created_by': ggrc_utils.created_by_stub, 'last_submitted_by': ggrc_utils.last_submitted_by_stub, 'last_verified_by': ggrc_utils.last_verified_by_stub, } _api_attrs = reflection.ApiAttributes( 'risk_type', 'threat_source', 'threat_event', 'vulnerability', 'external_id', 'due_date', reflection.ExternalUserAttribute('created_by', force_create=True), reflection.ExternalUserAttribute('last_submitted_by', force_create=True), reflection.ExternalUserAttribute('last_verified_by', force_create=True), 'last_submitted_at', 'last_verified_at', 'external_slug', 'review_status', 'review_status_display_name', ) _aliases = { "description": { "display_name": "Description", "mandatory": True }, "risk_type": { "display_name": "Risk Type", "mandatory": False }, "threat_source": { "display_name": "Threat Source", "mandatory": False }, "threat_event": { "display_name": "Threat Event", "mandatory": False }, "vulnerability": { "display_name": "Vulnerability", "mandatory": False }, "documents_file": None, "status": { "display_name": "State", "mandatory": False, "description": "Options are: \n {}".format('\n'.join( mixins.BusinessObject.VALID_STATES)) }, "review_status": { "display_name": "Review State", "mandatory": False, "filter_only": True, }, "review_status_display_name": { "display_name": "Review Status", "mandatory": False, }, "due_date": { "display_name": "Due Date", "mandatory": False, }, "created_by": { "display_name": "Created By", "mandatory": False, }, "last_submitted_at": { "display_name": "Last Owner Reviewed Date", "mandatory": False, }, "last_submitted_by": { "display_name": "Last Owner Reviewed By", "mandatory": False, }, "last_verified_at": { "display_name": "Last Compliance Reviewed Date", "mandatory": False, }, "last_verified_by": { "display_name": "Last Compliance Reviewed By", "mandatory": False, }, } def log_json(self): res = super(Risk, self).log_json() res["created_by"] = ggrc_utils.created_by_stub(self) res["last_submitted_by"] = ggrc_utils.last_submitted_by_stub(self) res["last_verified_by"] = ggrc_utils.last_verified_by_stub(self) return res