feat: Hesitations
parent
92bc2a66df
commit
861d9f72bd
|
@ -1,5 +1,8 @@
|
|||
# Changelog
|
||||
|
||||
# 0.12.0
|
||||
|
||||
* Added hesitations, which signify mistrust against instances. A softer form of censure, to use in silencing or closer attention instead of blocking.
|
||||
# 0.11.1
|
||||
|
||||
* Fixed censure filtering reasons using "AND" instead of "OR" as join
|
||||
|
|
|
@ -54,9 +54,19 @@ class Models:
|
|||
'domains': fields.List(fields.String(description="The instance domains as a list.")),
|
||||
'csv': fields.String(description="The instance domains as a csv."),
|
||||
})
|
||||
self.input_censures_modify = api.model('ModifyCensure', {
|
||||
'reason': fields.String(required=False, description="The reason for this censure. No profanity or hate speech allowed!", example="csam"),
|
||||
'evidence': fields.String(required=False, description="The evidence for this censure. Typically URL but can be a long form of anything you feel appropriate.", example="https://link.to/your/evidence", max_length=1000),
|
||||
self.response_model_dubious_instances = api.inherit('DubiousInstanceDetails', self.response_model_instances, {
|
||||
'hesitation_reasons': fields.List(fields.String(description="The reasons instances have given for hesitating against this instance")),
|
||||
'hesitation_evidence': fields.List(fields.String(description="Evidence justifying this hesitation, typically should be one or more URLs.")),
|
||||
'hesitation_count': fields.Integer(description="The amount of hesitations this instance has received from the reference instances"),
|
||||
})
|
||||
self.response_model_model_Hesitations_get = api.model('DubiousInstances', {
|
||||
'instances': fields.List(fields.Nested(self.response_model_dubious_instances)),
|
||||
'domains': fields.List(fields.String(description="The instance domains as a list.")),
|
||||
'csv': fields.String(description="The instance domains as a csv."),
|
||||
})
|
||||
self.input_censures_modify = api.model('ModifyCensureHesitations', {
|
||||
'reason': fields.String(required=False, description="The reason for this censure/hesitation. No profanity or hate speech allowed!", example="csam"),
|
||||
'evidence': fields.String(required=False, description="The evidence for this censure/hesitation. Typically URL but can be a long form of anything you feel appropriate.", example="https://link.to/your/evidence", max_length=1000),
|
||||
})
|
||||
self.response_model_api_key_reset = api.model('ApiKeyReset', {
|
||||
"message": fields.String(default='OK',required=True, description="The result of this operation."),
|
||||
|
|
|
@ -2,6 +2,7 @@ import fediseer.apis.v1.base as base
|
|||
import fediseer.apis.v1.whitelist as whitelist
|
||||
import fediseer.apis.v1.endorsements as endorsements
|
||||
import fediseer.apis.v1.censures as censures
|
||||
import fediseer.apis.v1.hesitations as hesitations
|
||||
import fediseer.apis.v1.guarantees as guarantees
|
||||
import fediseer.apis.v1.activitypub as activitypub
|
||||
import fediseer.apis.v1.badges as badges
|
||||
|
@ -19,6 +20,8 @@ api.add_resource(endorsements.Endorsements, "/endorsements/<string:domain>")
|
|||
api.add_resource(endorsements.Approvals, "/approvals/<string:domains_csv>")
|
||||
api.add_resource(censures.Censures, "/censures/<string:domain>")
|
||||
api.add_resource(censures.CensuresGiven, "/censures_given/<string:domains_csv>")
|
||||
api.add_resource(hesitations.Hesitations, "/hesitations/<string:domain>")
|
||||
api.add_resource(hesitations.HesitationsGiven, "/hesitations_given/<string:domains_csv>")
|
||||
api.add_resource(guarantees.Guarantors, "/guarantors/<string:domain>")
|
||||
api.add_resource(guarantees.Guarantees, "/guarantees/<string:domain>")
|
||||
api.add_resource(badges.GuaranteeBadge, "/badges/guarantees/<string:domain>.svg")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from fediseer.apis.v1.base import *
|
||||
from fediseer.classes.instance import Censure,Endorsement
|
||||
from fediseer.classes.instance import Censure
|
||||
from fediseer.utils import sanitize_string
|
||||
from fediseer.classes.reports import Report
|
||||
from fediseer import enums
|
||||
|
@ -116,7 +116,7 @@ class Censures(Resource):
|
|||
|
||||
|
||||
@api.expect(put_parser,models.input_censures_modify, validate=True)
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Endorse Instance')
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Censure Instance')
|
||||
@api.response(400, 'Bad Request', models.response_model_error)
|
||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||
@api.response(403, 'Not Guaranteed', models.response_model_error)
|
||||
|
@ -181,7 +181,7 @@ class Censures(Resource):
|
|||
|
||||
|
||||
@api.expect(patch_parser,models.input_censures_modify, validate=True)
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Endorse Instance')
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Modify Instance Censure')
|
||||
@api.response(400, 'Bad Request', models.response_model_error)
|
||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||
@api.response(403, 'Not Guaranteed', models.response_model_error)
|
||||
|
@ -233,7 +233,7 @@ class Censures(Resource):
|
|||
delete_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||
|
||||
@api.expect(delete_parser)
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Withdraw Instance Endorsement')
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Withdraw Instance Censure')
|
||||
@api.response(400, 'Bad Request', models.response_model_error)
|
||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
from fediseer.apis.v1.base import *
|
||||
from fediseer.classes.instance import Hesitation
|
||||
from fediseer.utils import sanitize_string
|
||||
from fediseer.classes.reports import Report
|
||||
from fediseer import enums
|
||||
|
||||
class HesitationsGiven(Resource):
|
||||
get_parser = reqparse.RequestParser()
|
||||
get_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||
get_parser.add_argument("csv", required=False, type=bool, help="Set to true to return just the domains as a csv. Mutually exclusive with domains", location="args")
|
||||
get_parser.add_argument("domains", required=False, type=bool, help="Set to true to return just the domains as a list. Mutually exclusive with csv", location="args")
|
||||
get_parser.add_argument("min_hesitations", required=False, default=1, type=int, help="Limit to this amount of hesitations of more", location="args")
|
||||
get_parser.add_argument("reasons_csv", required=False, type=str, help="Only retrieve hesitations where their reasons include any of the text in this csv", location="args")
|
||||
|
||||
@api.expect(get_parser)
|
||||
@cache.cached(timeout=10, query_string=True)
|
||||
@api.marshal_with(models.response_model_model_Hesitations_get, code=200, description='Instances', skip_none=True)
|
||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||
def get(self, domains_csv):
|
||||
'''Display all hesitations given out by one or more domains
|
||||
You can pass a comma-separated list of domain names
|
||||
and the results will be a set of all their hesitations together.
|
||||
'''
|
||||
self.args = self.get_parser.parse_args()
|
||||
domains_list = domains_csv.split(',')
|
||||
instances = database.find_multiple_instance_by_domains(domains_list)
|
||||
if not instances:
|
||||
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
||||
if self.args.min_hesitations > len(domains_list):
|
||||
raise e.BadRequest(f"You cannot request more hesitations than the amount of reference domains")
|
||||
instance_details = []
|
||||
for c_instance in database.get_all_dubious_instances_by_hesitant_id([instance.id for instance in instances]):
|
||||
hesitations = database.get_all_hesitation_reasons_for_dubious_id(c_instance.id, [instance.id for instance in instances])
|
||||
hesitation_count = len(hesitations)
|
||||
hesitations = [c for c in hesitations if c.reason is not None]
|
||||
c_instance_details = c_instance.get_details()
|
||||
skip_instance = True
|
||||
if self.args.reasons_csv:
|
||||
reasons_filter = [r.strip().lower() for r in self.args.reasons_csv.split(',')]
|
||||
reasons_filter = set(reasons_filter)
|
||||
for r in reasons_filter:
|
||||
reason_filter_counter = 0
|
||||
for hesitation in hesitations:
|
||||
if r in hesitation.reason.lower():
|
||||
reason_filter_counter += 1
|
||||
if reason_filter_counter >= self.args.min_hesitations:
|
||||
skip_instance = False
|
||||
break
|
||||
elif hesitation_count >= self.args.min_hesitations:
|
||||
skip_instance = False
|
||||
if skip_instance:
|
||||
continue
|
||||
c_instance_details["hesitation_reasons"] = [hesitation.reason for hesitation in hesitations]
|
||||
c_instance_details["hesitation_evidence"] = [hesitation.evidence for hesitation in hesitations if hesitation.evidence is not None]
|
||||
c_instance_details["hesitation_count"] = hesitation_count
|
||||
instance_details.append(c_instance_details)
|
||||
if self.args.csv:
|
||||
return {"csv": ",".join([instance["domain"] for instance in instance_details])},200
|
||||
if self.args.domains:
|
||||
return {"domains": [instance["domain"] for instance in instance_details]},200
|
||||
|
||||
return {"instances": instance_details},200
|
||||
|
||||
class Hesitations(Resource):
|
||||
get_parser = reqparse.RequestParser()
|
||||
get_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||
get_parser.add_argument("csv", required=False, type=bool, help="Set to true to return just the domains as a csv. Mutually exclusive with domains", location="args")
|
||||
get_parser.add_argument("domains", required=False, type=bool, help="Set to true to return just the domains as a list. Mutually exclusive with csv", location="args")
|
||||
|
||||
@api.expect(get_parser)
|
||||
@cache.cached(timeout=10, query_string=True)
|
||||
@api.marshal_with(models.response_model_model_Hesitations_get, code=200, description='Instances', skip_none=True)
|
||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||
def get(self, domain):
|
||||
'''Display all hesitations received by a specific domain
|
||||
'''
|
||||
self.args = self.get_parser.parse_args()
|
||||
instance = database.find_instance_by_domain(domain)
|
||||
if not instance:
|
||||
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
||||
instance_details = []
|
||||
for c_instance in database.get_all_hesitant_instances_by_dubious_id(instance.id):
|
||||
hesitations = database.get_all_hesitation_reasons_for_dubious_id(instance.id, [c_instance.id])
|
||||
hesitations = [c for c in hesitations if c.reason is not None]
|
||||
c_instance_details = c_instance.get_details()
|
||||
if len(hesitations) > 0:
|
||||
c_instance_details["hesitation_reasons"] = [hesitation.reason for hesitation in hesitations]
|
||||
c_instance_details["hesitation_evidence"] = [hesitation.evidence for hesitation in hesitations if hesitation.evidence is not None]
|
||||
instance_details.append(c_instance_details)
|
||||
if self.args.csv:
|
||||
return {"csv": ",".join([instance["domain"] for instance in instance_details])},200
|
||||
if self.args.domains:
|
||||
return {"domains": [instance["domain"] for instance in instance_details]},200
|
||||
return {"instances": instance_details},200
|
||||
|
||||
put_parser = reqparse.RequestParser()
|
||||
put_parser.add_argument("apikey", type=str, required=True, help="The sending instance's API key.", location='headers')
|
||||
put_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||
put_parser.add_argument("reason", default=None, type=str, required=False, location="json")
|
||||
put_parser.add_argument("evidence", default=None, type=str, required=False, location="json")
|
||||
|
||||
|
||||
@api.expect(put_parser,models.input_censures_modify, validate=True)
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Mistrust Instance')
|
||||
@api.response(400, 'Bad Request', models.response_model_error)
|
||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||
@api.response(403, 'Not Guaranteed', models.response_model_error)
|
||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||
def put(self, domain):
|
||||
'''Hesitate against an instance
|
||||
A hesitation signifies a mistrust from your instance to how that instance is being run.
|
||||
'''
|
||||
self.args = self.put_parser.parse_args()
|
||||
if not self.args.apikey:
|
||||
raise e.Unauthorized("You must provide the API key that was PM'd to your admin account")
|
||||
instance = database.find_instance_by_api_key(self.args.apikey)
|
||||
if not instance:
|
||||
raise e.NotFound(f"No Instance found matching provided API key and domain. Have you remembered to register it?")
|
||||
if len(instance.guarantors) == 0:
|
||||
raise e.Forbidden("Only guaranteed instances can hesitation others.")
|
||||
if instance.domain == domain:
|
||||
raise e.BadRequest("You're a mad lad, but you can't hesitation yourself.")
|
||||
unbroken_chain, chainbreaker = database.has_unbroken_chain(instance.id)
|
||||
if not unbroken_chain:
|
||||
raise e.Forbidden(f"Guarantee chain for this instance has been broken. Chain ends at {chainbreaker.domain}!")
|
||||
target_instance, nodeinfo, admin_usernames = ensure_instance_registered(domain, allow_unreachable=True)
|
||||
if not target_instance:
|
||||
raise e.NotFound(f"Something went wrong trying to register this instance.")
|
||||
if not target_instance:
|
||||
raise e.BadRequest("Instance to hesitation not found")
|
||||
if database.get_endorsement(target_instance.id,instance.id):
|
||||
raise e.BadRequest("You can't hesitate against an instance you've endorsed! Please withdraw the endorsement first.")
|
||||
if database.get_hesitation(target_instance.id,instance.id):
|
||||
return {"message":'OK'}, 200
|
||||
|
||||
reason = self.args.reason
|
||||
if reason is not None:
|
||||
reason = sanitize_string(reason)
|
||||
evidence = self.args.evidence
|
||||
if evidence is not None:
|
||||
evidence = sanitize_string(evidence)
|
||||
new_hesitation = Hesitation(
|
||||
hesitant_id=instance.id,
|
||||
dubious_id=target_instance.id,
|
||||
reason=reason,
|
||||
evidence=evidence,
|
||||
)
|
||||
db.session.add(new_hesitation)
|
||||
new_report = Report(
|
||||
source_domain=instance.domain,
|
||||
target_domain=target_instance.domain,
|
||||
report_type=enums.ReportType.HESITATION,
|
||||
report_activity=enums.ReportActivity.ADDED,
|
||||
)
|
||||
db.session.add(new_report)
|
||||
db.session.commit()
|
||||
logger.info(f"{instance.domain} hesitated against {domain}")
|
||||
return {"message":'Changed'}, 200
|
||||
|
||||
|
||||
patch_parser = reqparse.RequestParser()
|
||||
patch_parser.add_argument("apikey", type=str, required=True, help="The sending instance's API key.", location='headers')
|
||||
patch_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||
patch_parser.add_argument("reason", default=None, type=str, required=False, location="json")
|
||||
patch_parser.add_argument("evidence", default=None, type=str, required=False, location="json")
|
||||
|
||||
|
||||
@api.expect(patch_parser,models.input_censures_modify, validate=True)
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Modify Instance Hesitation')
|
||||
@api.response(400, 'Bad Request', models.response_model_error)
|
||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||
@api.response(403, 'Not Guaranteed', models.response_model_error)
|
||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||
def patch(self, domain):
|
||||
'''Modify an instance's Hesitation
|
||||
'''
|
||||
self.args = self.patch_parser.parse_args()
|
||||
if not self.args.apikey:
|
||||
raise e.Unauthorized("You must provide the API key that was PM'd to your admin account")
|
||||
instance = database.find_instance_by_api_key(self.args.apikey)
|
||||
if not instance:
|
||||
raise e.NotFound(f"No Instance found matching provided API key and domain. Have you remembered to register it?")
|
||||
target_instance = database.find_instance_by_domain(domain=domain)
|
||||
if not target_instance:
|
||||
raise e.BadRequest("Instance from which to modify hesitation not found")
|
||||
hesitation = database.get_hesitation(target_instance.id,instance.id)
|
||||
if not hesitation:
|
||||
raise e.BadRequest(f"No hesitation found for {domain} from {instance.domain}")
|
||||
changed = False
|
||||
reason = self.args.reason
|
||||
if reason is not None:
|
||||
reason = sanitize_string(reason)
|
||||
if hesitation.reason != reason:
|
||||
hesitation.reason = reason
|
||||
changed = True
|
||||
evidence = self.args.evidence
|
||||
if evidence is not None:
|
||||
evidence = sanitize_string(evidence)
|
||||
if hesitation.evidence != evidence:
|
||||
hesitation.evidence = evidence
|
||||
changed = True
|
||||
if changed is False:
|
||||
return {"message":'OK'}, 200
|
||||
new_report = Report(
|
||||
source_domain=instance.domain,
|
||||
target_domain=target_instance.domain,
|
||||
report_type=enums.ReportType.HESITATION,
|
||||
report_activity=enums.ReportActivity.MODIFIED,
|
||||
)
|
||||
db.session.add(new_report)
|
||||
db.session.commit()
|
||||
logger.info(f"{instance.domain} Modfied hesitation for {domain}")
|
||||
return {"message":'Changed'}, 200
|
||||
|
||||
|
||||
delete_parser = reqparse.RequestParser()
|
||||
delete_parser.add_argument("apikey", type=str, required=True, help="The sending instance's API key.", location='headers')
|
||||
delete_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||
|
||||
@api.expect(delete_parser)
|
||||
@api.marshal_with(models.response_model_simple_response, code=200, description='Withdraw Instance Hesitation')
|
||||
@api.response(400, 'Bad Request', models.response_model_error)
|
||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||
def delete(self,domain):
|
||||
'''Withdraw an instance hesitation
|
||||
'''
|
||||
self.args = self.delete_parser.parse_args()
|
||||
if not self.args.apikey:
|
||||
raise e.Unauthorized("You must provide the API key that was PM'd to your admin account")
|
||||
instance = database.find_instance_by_api_key(self.args.apikey)
|
||||
if not instance:
|
||||
raise e.NotFound(f"No Instance found matching provided API key and domain. Have you remembered to register it?")
|
||||
target_instance = database.find_instance_by_domain(domain=domain)
|
||||
if not target_instance:
|
||||
raise e.BadRequest("Instance from which to withdraw hesitation not found")
|
||||
hesitation = database.get_hesitation(target_instance.id,instance.id)
|
||||
if not hesitation:
|
||||
return {"message":'OK'}, 200
|
||||
db.session.delete(hesitation)
|
||||
new_report = Report(
|
||||
source_domain=instance.domain,
|
||||
target_domain=target_instance.domain,
|
||||
report_type=enums.ReportType.HESITATION,
|
||||
report_activity=enums.ReportActivity.DELETED,
|
||||
)
|
||||
db.session.add(new_report)
|
||||
db.session.commit()
|
||||
logger.info(f"{instance.domain} Withdrew hesitation from {domain}")
|
||||
return {"message":'Changed'}, 200
|
|
@ -54,5 +54,4 @@ class Report(Resource):
|
|||
'created': r.created.isoformat() + 'Z',
|
||||
}
|
||||
)
|
||||
logger.debug(report_response)
|
||||
return report_response,200
|
||||
|
|
|
@ -60,6 +60,18 @@ class Censure(db.Model):
|
|||
censured_instance = db.relationship("Instance", back_populates="censures_received", foreign_keys=[censured_id])
|
||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||
|
||||
class Hesitation(db.Model):
|
||||
__tablename__ = "hesitations"
|
||||
__table_args__ = (UniqueConstraint('hesitant_id', 'dubious_id', name='hesitations_hesitant_id_dubious_id'),)
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
||||
evidence = db.Column(db.Text, unique=False, nullable=True, index=False)
|
||||
hesitant_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
||||
hesitating_instance = db.relationship("Instance", back_populates="hesitations_given", foreign_keys=[hesitant_id])
|
||||
dubious_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
||||
dubious_instance = db.relationship("Instance", back_populates="hesitations_received", foreign_keys=[dubious_id])
|
||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||
|
||||
|
||||
class Instance(db.Model):
|
||||
__tablename__ = "instances"
|
||||
|
@ -80,6 +92,8 @@ class Instance(db.Model):
|
|||
endorsements = db.relationship("Endorsement", back_populates="endorsed_instance", cascade="all, delete-orphan", foreign_keys=[Endorsement.endorsed_id])
|
||||
censures_given = db.relationship("Censure", back_populates="censuring_instance", cascade="all, delete-orphan", foreign_keys=[Censure.censuring_id])
|
||||
censures_received = db.relationship("Censure", back_populates="censured_instance", cascade="all, delete-orphan", foreign_keys=[Censure.censured_id])
|
||||
hesitations_given = db.relationship("Hesitation", back_populates="hesitating_instance", cascade="all, delete-orphan", foreign_keys=[Hesitation.hesitant_id])
|
||||
hesitations_received = db.relationship("Hesitation", back_populates="dubious_instance", cascade="all, delete-orphan", foreign_keys=[Hesitation.dubious_id])
|
||||
guarantees = db.relationship("Guarantee", back_populates="guarantor_instance", cascade="all, delete-orphan", foreign_keys=[Guarantee.guarantor_id])
|
||||
guarantors = db.relationship("Guarantee", back_populates="guaranteed_instance", cascade="all, delete-orphan", foreign_keys=[Guarantee.guaranteed_id])
|
||||
rejections = db.relationship("RejectionRecord", back_populates="rejector_instance", cascade="all, delete-orphan", foreign_keys=[RejectionRecord.rejector_id])
|
||||
|
|
|
@ -8,7 +8,7 @@ from sqlalchemy.orm import noload
|
|||
from fediseer.flask import db, SQLITE_MODE
|
||||
from fediseer.utils import hash_api_key
|
||||
from sqlalchemy.orm import joinedload
|
||||
from fediseer.classes.instance import Instance, Endorsement, Guarantee, RejectionRecord, Censure
|
||||
from fediseer.classes.instance import Instance, Endorsement, Guarantee, RejectionRecord, Censure, Hesitation
|
||||
from fediseer.classes.user import Claim, User
|
||||
from fediseer.classes.reports import Report
|
||||
from fediseer import enums
|
||||
|
@ -106,6 +106,47 @@ def get_all_censure_reasons_for_censured_id(censured_id, censuring_ids):
|
|||
return query.all()
|
||||
|
||||
|
||||
def get_all_dubious_instances_by_hesitant_id(hesitant_ids):
|
||||
query = db.session.query(
|
||||
Instance
|
||||
).outerjoin(
|
||||
Instance.hesitations_received,
|
||||
).options(
|
||||
joinedload(Instance.hesitations_received),
|
||||
).filter(
|
||||
Hesitation.hesitant_id.in_(hesitant_ids)
|
||||
).group_by(
|
||||
Instance.id
|
||||
)
|
||||
return query.all()
|
||||
|
||||
def get_all_hesitant_instances_by_dubious_id(dubious_id):
|
||||
query = db.session.query(
|
||||
Instance
|
||||
).outerjoin(
|
||||
Instance.hesitations_given,
|
||||
).options(
|
||||
joinedload(Instance.hesitations_given),
|
||||
).filter(
|
||||
Hesitation.dubious_id == dubious_id
|
||||
).group_by(
|
||||
Instance.id
|
||||
)
|
||||
return query.all()
|
||||
|
||||
def get_all_hesitation_reasons_for_dubious_id(dubious_id, hesitant_ids):
|
||||
query = Hesitation.query.filter(
|
||||
and_(
|
||||
Hesitation.dubious_id == dubious_id,
|
||||
Hesitation.hesitant_id.in_(hesitant_ids),
|
||||
)
|
||||
).with_entities(
|
||||
Hesitation.reason,
|
||||
Hesitation.evidence,
|
||||
)
|
||||
return query.all()
|
||||
|
||||
|
||||
|
||||
def get_all_guaranteed_instances_by_guarantor_id(guarantor_id):
|
||||
query = db.session.query(
|
||||
|
@ -231,6 +272,13 @@ def get_censure(instance_id, censuring_instance_id):
|
|||
)
|
||||
return query.first()
|
||||
|
||||
def get_hesitation(instance_id, hesitant_instance_id):
|
||||
query = Hesitation.query.filter_by(
|
||||
dubious_id=instance_id,
|
||||
hesitant_id=hesitant_instance_id,
|
||||
)
|
||||
return query.first()
|
||||
|
||||
def has_recent_endorsement(instance_id):
|
||||
query = Endorsement.query.filter(
|
||||
Endorsement.endorsed_id == instance_id,
|
||||
|
|
|
@ -4,7 +4,7 @@ class ReportType(enum.Enum):
|
|||
GUARANTEE = 0
|
||||
ENDORSEMENT = 1
|
||||
CENSURE = 2
|
||||
RESTRICTION = 3
|
||||
HESITATION = 3
|
||||
|
||||
class ReportActivity(enum.Enum):
|
||||
ADDED = 0
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TYPE reporttype
|
||||
RENAME VALUE 'RESTRICTION' TO 'HESITATION';
|
Loading…
Reference in New Issue